]> 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-2012 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   double
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.7328*x+0.4296*y-0.1624*z;
133   m=(-0.7036*x+1.6975*y+0.0415*z);
134   s=0.0030*x+0.0136*y+0.9834*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.950470)
163 #define D65Y  (1.0)
164 #define D65Z  (1.088830)
165 #define CIEEpsilon  (216.0/24389.0)
166 #define CIEK  (24389.0/27.0)
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.0)/116.0;
180   if ((Y/D65Y) > CIEEpsilon)
181     y=pow(Y/D65Y,1.0/3.0);
182   else
183     y=(CIEK*Y/D65Y+16.0)/116.0;
184   if ((Z/D65Z) > CIEEpsilon)
185     z=pow(Z/D65Z,1.0/3.0);
186   else
187     z=(CIEK*Z/D65Z+16.0)/116.0;
188   *L=((116.0*y)-16.0)/100.0;
189   *a=(500.0*(x-y))/255.0+0.5;
190   *b=(200.0*(y-z))/255.0+0.5;
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.0*pow(Y/D65Y,1.0/3.0)-16.0);
204   else
205     *L=CIEK*(Y/D65Y);
206   alpha=MagickEpsilonReciprocal(X+15.0*Y+3.0*Z);
207   *u=13.0*(*L)*((4.0*alpha*X)-(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z)));
208   *v=13.0*(*L)*((9.0*alpha*Y)-(9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z)));
209   *L/=100.0;
210   *u=(*u+134.0)/354.0;
211   *v=(*v+140.0)/262.0;
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=InversesRGBCompandor((double) GetPixelCyan(image,q));
298           magenta=InversesRGBCompandor((double) GetPixelMagenta(image,q));
299           yellow=InversesRGBCompandor((double) 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=InversesRGBCompandor(pixel.red);
367           pixel.green=InversesRGBCompandor(pixel.green);
368           pixel.blue=InversesRGBCompandor(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=InversesRGBCompandor((double) GetPixelRed(image,q));
431           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
432           blue=InversesRGBCompandor((double) GetPixelBlue(image,q));
433           gray=0.298839*red+0.586811*green+0.114350*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=InversesRGBCompandor((double) GetPixelRed(image,q));
495           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
496           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
560           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
561           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
625           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
626           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
690           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
691           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
758           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
759           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
829           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
830           blue=InversesRGBCompandor((double) 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.0/MagickPI;
835           if (H < 0.0)
836             H+=1.0;
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=InversesRGBCompandor((double) GetPixelRed(image,q));
902           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
903           blue=InversesRGBCompandor((double) 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.0/1.7)
923 #define FilmGamma  0.6
924 #define ReferenceBlack  95.0
925 #define ReferenceWhite  685.0
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=MagickEpsilonReciprocal(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)*
967         0.002/film_gamma);
968 #if defined(MAGICKCORE_OPENMP_SUPPORT)
969       #pragma omp parallel for schedule(static) \
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)*
975           0.002/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=InversesRGBCompandor((double) GetPixelRed(image,q));
1009           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
1010           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
1080           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
1081           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
1144           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
1145           blue=InversesRGBCompandor((double) GetPixelBlue(image,q));
1146           gray=0.212600*red+0.715200*green+0.072200*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=InversesRGBCompandor((double) GetPixelRed(image,q));
1205           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
1206           blue=InversesRGBCompandor((double) 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=InversesRGBCompandor((double) GetPixelRed(image,q));
1269           green=InversesRGBCompandor((double) GetPixelGreen(image,q));
1270           blue=InversesRGBCompandor((double) 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.0)/2.0;
1319       primary_info.z=(double) (MaxMap+1.0)/2.0;
1320 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1321       #pragma omp parallel for schedule(static) \
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=0.33333*i;
1327         y_map[i].x=0.33334*i;
1328         z_map[i].x=0.33333*i;
1329         x_map[i].y=0.50000*i;
1330         y_map[i].y=0.00000*i;
1331         z_map[i].y=(-0.50000)*i;
1332         x_map[i].z=(-0.25000)*i;
1333         y_map[i].z=0.50000*i;
1334         z_map[i].z=(-0.25000)*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.2988390*R+0.5868110*G+0.1143500*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.0)/2.0;
1352       primary_info.z=(double) (MaxMap+1.0)/2.0;
1353 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1354       #pragma omp parallel for schedule(static) \
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=0.298839*i;
1360         y_map[i].x=0.586811*i;
1361         z_map[i].x=0.114350*i;
1362         x_map[i].y=(-0.1687367)*i;
1363         y_map[i].y=(-0.331264)*i;
1364         z_map[i].y=0.500000*i;
1365         x_map[i].z=0.500000*i;
1366         y_map[i].z=(-0.418688)*i;
1367         z_map[i].z=(-0.081312)*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.0)/2.0;
1384       primary_info.z=(double) (MaxMap+1.0)/2.0;
1385 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1386       #pragma omp parallel for schedule(static) \
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=0.212600*i;
1392         y_map[i].x=0.715200*i;
1393         z_map[i].x=0.072200*i;
1394         x_map[i].y=(-0.114572)*i;
1395         y_map[i].y=(-0.385428)*i;
1396         z_map[i].y=0.500000*i;
1397         x_map[i].z=0.500000*i;
1398         y_map[i].z=(-0.454153)*i;
1399         z_map[i].z=(-0.045847)*i;
1400       }
1401       break;
1402     }
1403     case YCCColorspace:
1404     {
1405       /*
1406         Initialize YCC tables:
1407
1408           Y =  0.298839*R+0.586811*G+0.114350*B
1409           C1= -0.298839*R-0.586811*G+0.88600*B
1410           C2=  0.70100*R-0.586811*G-0.114350*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.018*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.298839*R+0.586811*G+0.114350*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.0)/2.0;
1455       primary_info.z=(double) (MaxMap+1.0)/2.0;
1456 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1457       #pragma omp parallel for schedule(static) \
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=0.298839*i;
1463         y_map[i].x=0.586811*i;
1464         z_map[i].x=0.114350*i;
1465         x_map[i].y=0.595716*i;
1466         y_map[i].y=(-0.274453)*i;
1467         z_map[i].y=(-0.321263)*i;
1468         x_map[i].z=0.211456*i;
1469         y_map[i].z=(-0.522591)*i;
1470         z_map[i].z=0.311135*i;
1471       }
1472       break;
1473     }
1474     case YPbPrColorspace:
1475     {
1476       /*
1477         Initialize YPbPr tables (ITU-R BT.601):
1478
1479           Y =  0.2988390*R+0.5868110*G+0.1143500*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.0)/2.0;
1487       primary_info.z=(double) (MaxMap+1.0)/2.0;
1488 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1489       #pragma omp parallel for schedule(static) \
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=0.298839*i;
1495         y_map[i].x=0.586811*i;
1496         z_map[i].x=0.114350*i;
1497         x_map[i].y=(-0.1687367)*i;
1498         y_map[i].y=(-0.331264)*i;
1499         z_map[i].y=0.500000*i;
1500         x_map[i].z=0.500000*i;
1501         y_map[i].z=(-0.418688)*i;
1502         z_map[i].z=(-0.081312)*i;
1503       }
1504       break;
1505     }
1506     case YUVColorspace:
1507     {
1508       /*
1509         Initialize YUV tables:
1510
1511           Y =  0.298839*R+0.586811*G+0.114350*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.0)/2.0;
1519       primary_info.z=(double) (MaxMap+1.0)/2.0;
1520 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1521       #pragma omp parallel for schedule(static) \
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=0.298839*i;
1527         y_map[i].x=0.586811*i;
1528         z_map[i].x=0.114350*i;
1529         x_map[i].y=(-0.147130)*i;
1530         y_map[i].y=(-0.288860)*i;
1531         z_map[i].y=0.436000*i;
1532         x_map[i].z=0.615000*i;
1533         y_map[i].z=(-0.514990)*i;
1534         z_map[i].z=(-0.100001)*i;
1535       }
1536       break;
1537     }
1538     default:
1539     {
1540       /*
1541         Linear conversion tables.
1542       */
1543 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1544       #pragma omp parallel for schedule(static) \
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=1.0*i;
1550         y_map[i].x=0.0f;
1551         z_map[i].x=0.0f;
1552         x_map[i].y=0.0f;
1553         y_map[i].y=1.0*i;
1554         z_map[i].y=0.0f;
1555         x_map[i].z=0.0f;
1556         y_map[i].z=0.0f;
1557         z_map[i].z=1.0*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(InversesRGBCompandor((double)
1609             GetPixelRed(image,q))));
1610           green=ScaleQuantumToMap(ClampToQuantum(InversesRGBCompandor((double)
1611             GetPixelGreen(image,q))));
1612           blue=ScaleQuantumToMap(ClampToQuantum(InversesRGBCompandor((double)
1613             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(InversesRGBCompandor(
1661           image->colormap[i].red)));
1662         green=ScaleQuantumToMap(ClampToQuantum(InversesRGBCompandor(
1663           image->colormap[i].green)));
1664         blue=ScaleQuantumToMap(ClampToQuantum(InversesRGBCompandor(
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.000;
1723   (void) ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
1724   if (IssRGBColorspace(colorspace) != MagickFalse)
1725     {
1726       image->rendering_intent=PerceptualIntent;
1727       image->gamma=1.000/2.200;
1728       image->chromaticity.red_primary.x=0.6400;
1729       image->chromaticity.red_primary.y=0.3300;
1730       image->chromaticity.red_primary.z=0.0300;
1731       image->chromaticity.green_primary.x=0.3000;
1732       image->chromaticity.green_primary.y=0.6000;
1733       image->chromaticity.green_primary.z=0.1000;
1734       image->chromaticity.blue_primary.x=0.1500;
1735       image->chromaticity.blue_primary.y=0.0600;
1736       image->chromaticity.blue_primary.z=0.7900;
1737       image->chromaticity.white_point.x=0.3127;
1738       image->chromaticity.white_point.y=0.3290;
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.0*L+16.0)/116.0;
1870   x=y+255.0*(a-0.5)/500.0;
1871   z=y-255.0*(b-0.5)/200.0;
1872   if ((x*x*x) > CIEEpsilon)
1873     x=(x*x*x);
1874   else
1875     x=(116.0*x-16.0)/CIEK;
1876   if ((y*y*y) > CIEEpsilon)
1877     y=(y*y*y);
1878   else
1879     y=(100.0*L)/CIEK;
1880   if ((z*z*z) > CIEEpsilon)
1881     z=(z*z*z);
1882   else
1883     z=(116*z-16.0)/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.0*L) > (CIEK*CIEEpsilon))
1896     *Y=(double) pow(((100.0*L)+16.0)/116.0,3.0);
1897   else
1898     *Y=(100.0*L)/CIEK;
1899   *X=((*Y*((39.0*(100.0*L)/((262.0*v-140.0)+13.0*(100.0*L)*(9.0*D65Y/(D65X+
1900     15.0*D65Y+3.0*D65Z))))-5.0))+5.0*(*Y))/((((52.0*(100.0*L)/((354.0*u-134.0)+
1901     13.0*(100.0*L)*(4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z))))-1.0)/3.0)-(-1.0/3.0));
1902   *Z=(*X*(((52.0*(100.0*L)/((354.0*u-134.0)+13.0*(100.0*L)*(4.0*D65X/(D65X+
1903     15.0*D65Y+3.0*D65Z))))-1.0)/3.0))-5.0*(*Y);
1904 }
1905
1906 static inline ssize_t RoundToYCC(const double value)
1907 {
1908   if (value <= 0.0)
1909     return(0);
1910   if (value >= 1388.0)
1911     return(1388);
1912   return((ssize_t) (value+0.5));
1913 }
1914
1915 static inline void ConvertXYZToRGB(const double x,const double y,
1916   const double z,double *red,double *green,double *blue)
1917 {
1918   double
1919     b,
1920     g,
1921     r;
1922
1923   /*
1924     Convert XYZ to sRGB colorspace.
1925   */
1926   assert(red != (double *) NULL);
1927   assert(green != (double *) NULL);
1928   assert(blue != (double *) NULL);
1929   r=3.2406*x-1.5372*y-0.4986*z;
1930   g=(-0.9689*x+1.8758*y+0.0415*z);
1931   b=0.0557*x-0.2040*y+1.0570*z;
1932   *red=QuantumRange*r;
1933   *green=QuantumRange*g;
1934   *blue=QuantumRange*b;
1935 }
1936
1937 static inline void ConvertCMYKToRGB(PixelInfo *pixel)
1938 {
1939   pixel->red=((QuantumRange-(QuantumScale*pixel->red*
1940     (QuantumRange-pixel->black)+pixel->black)));
1941   pixel->green=((QuantumRange-(QuantumScale*pixel->green*
1942     (QuantumRange-pixel->black)+pixel->black)));
1943   pixel->blue=((QuantumRange-(QuantumScale*pixel->blue*
1944     (QuantumRange-pixel->black)+pixel->black)));
1945 }
1946
1947 static MagickBooleanType TransformsRGBImage(Image *image,
1948   const ColorspaceType colorspace,ExceptionInfo *exception)
1949 {
1950 #define TransformsRGBImageTag  "Transform/Image"
1951
1952 #if !defined(MAGICKCORE_HDRI_SUPPORT)
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 #endif
2190
2191   CacheView
2192     *image_view;
2193
2194   MagickBooleanType
2195     status;
2196
2197   MagickOffsetType
2198     progress;
2199
2200   register ssize_t
2201     i;
2202
2203   ssize_t
2204     y;
2205
2206   TransformPacket
2207     *y_map,
2208     *x_map,
2209     *z_map;
2210
2211   assert(image != (Image *) NULL);
2212   assert(image->signature == MagickSignature);
2213   if (image->debug != MagickFalse)
2214     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2215   status=MagickTrue;
2216   progress=0;
2217   switch (image->colorspace)
2218   {
2219     case CMYColorspace:
2220     {
2221       /*
2222         Transform image from CMY to sRGB.
2223       */
2224       if (image->storage_class == PseudoClass)
2225         {
2226           if (SyncImage(image,exception) == MagickFalse)
2227             return(MagickFalse);
2228           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2229             return(MagickFalse);
2230         }
2231       image_view=AcquireAuthenticCacheView(image,exception);
2232 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2233       #pragma omp parallel for schedule(static,4) shared(status) \
2234         dynamic_number_threads(image,image->columns,image->rows,1)
2235 #endif
2236       for (y=0; y < (ssize_t) image->rows; y++)
2237       {
2238         MagickBooleanType
2239           sync;
2240
2241         register ssize_t
2242           x;
2243
2244         register Quantum
2245           *restrict q;
2246
2247         if (status == MagickFalse)
2248           continue;
2249         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2250           exception);
2251         if (q == (Quantum *) NULL)
2252           {
2253             status=MagickFalse;
2254             continue;
2255           }
2256         for (x=0; x < (ssize_t) image->columns; x++)
2257         {
2258           double
2259             cyan,
2260             magenta,
2261             yellow;
2262
2263           cyan=sRGBCompandor((double) (QuantumRange-
2264             GetPixelCyan(image,q)));
2265           magenta=sRGBCompandor((double) (QuantumRange-
2266             GetPixelMagenta(image,q)));
2267           yellow=sRGBCompandor((double) (QuantumRange-
2268             GetPixelYellow(image,q)));
2269           SetPixelCyan(image,ClampToQuantum(cyan),q);
2270           SetPixelMagenta(image,ClampToQuantum(magenta),q);
2271           SetPixelYellow(image,ClampToQuantum(yellow),q);
2272           q+=GetPixelChannels(image);
2273         }
2274         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2275         if (sync == MagickFalse)
2276           status=MagickFalse;
2277       }
2278       image_view=DestroyCacheView(image_view);
2279       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2280         return(MagickFalse);
2281       return(status);
2282     }
2283     case CMYKColorspace:
2284     {
2285       PixelInfo
2286         zero;
2287
2288       /*
2289         Transform image from CMYK to sRGB.
2290       */
2291       if (image->storage_class == PseudoClass)
2292         {
2293           if (SyncImage(image,exception) == MagickFalse)
2294             return(MagickFalse);
2295           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2296             return(MagickFalse);
2297         }
2298       GetPixelInfo(image,&zero);
2299       image_view=AcquireAuthenticCacheView(image,exception);
2300 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2301       #pragma omp parallel for schedule(static,4) shared(status) \
2302         dynamic_number_threads(image,image->columns,image->rows,1)
2303 #endif
2304       for (y=0; y < (ssize_t) image->rows; y++)
2305       {
2306         MagickBooleanType
2307           sync;
2308
2309         PixelInfo
2310           pixel;
2311
2312         register ssize_t
2313           x;
2314
2315         register Quantum
2316           *restrict q;
2317
2318         if (status == MagickFalse)
2319           continue;
2320         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2321           exception);
2322         if (q == (Quantum *) NULL)
2323           {
2324             status=MagickFalse;
2325             continue;
2326           }
2327         pixel=zero;
2328         for (x=0; x < (ssize_t) image->columns; x++)
2329         {
2330           GetPixelInfoPixel(image,q,&pixel);
2331           ConvertCMYKToRGB(&pixel);
2332           pixel.red=sRGBCompandor(pixel.red);
2333           pixel.green=sRGBCompandor(pixel.green);
2334           pixel.blue=sRGBCompandor(pixel.blue);
2335           SetPixelInfoPixel(image,&pixel,q);
2336           q+=GetPixelChannels(image);
2337         }
2338         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2339         if (sync == MagickFalse)
2340           status=MagickFalse;
2341       }
2342       image_view=DestroyCacheView(image_view);
2343       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2344         return(MagickFalse);
2345       return(status);
2346     }
2347     case GRAYColorspace:
2348     case Rec601LumaColorspace:
2349     case Rec709LumaColorspace:
2350     {
2351       /*
2352         Transform linear GRAY to sRGB colorspace.
2353       */
2354       if (image->storage_class == PseudoClass)
2355         {
2356           if (SyncImage(image,exception) == MagickFalse)
2357             return(MagickFalse);
2358           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2359             return(MagickFalse);
2360         }
2361       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2362         return(MagickFalse);
2363       image_view=AcquireAuthenticCacheView(image,exception);
2364 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2365       #pragma omp parallel for schedule(static,4) shared(status) \
2366         dynamic_number_threads(image,image->columns,image->rows,1)
2367 #endif
2368       for (y=0; y < (ssize_t) image->rows; y++)
2369       {
2370         MagickBooleanType
2371           sync;
2372
2373         register ssize_t
2374           x;
2375
2376         register Quantum
2377           *restrict q;
2378
2379         if (status == MagickFalse)
2380           continue;
2381         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2382           exception);
2383         if (q == (Quantum *) NULL)
2384           {
2385             status=MagickFalse;
2386             continue;
2387           }
2388         for (x=(ssize_t) image->columns; x != 0; x--)
2389         {
2390           double
2391             gray;
2392
2393           gray=sRGBCompandor((double) GetPixelGray(image,q));
2394           SetPixelRed(image,ClampToQuantum(gray),q);
2395           SetPixelGreen(image,ClampToQuantum(gray),q);
2396           SetPixelBlue(image,ClampToQuantum(gray),q);
2397           q+=GetPixelChannels(image);
2398         }
2399         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2400         if (sync == MagickFalse)
2401           status=MagickFalse;
2402       }
2403       image_view=DestroyCacheView(image_view);
2404       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2405         return(MagickFalse);
2406       return(status);
2407     }
2408     case HCLColorspace:
2409     {
2410       /*
2411         Transform image from HCL to sRGB.
2412       */
2413       if (image->storage_class == PseudoClass)
2414         {
2415           if (SyncImage(image,exception) == MagickFalse)
2416             return(MagickFalse);
2417           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2418             return(MagickFalse);
2419         }
2420       image_view=AcquireAuthenticCacheView(image,exception);
2421 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2422       #pragma omp parallel for schedule(static,4) shared(status) \
2423         dynamic_number_threads(image,image->columns,image->rows,1)
2424 #endif
2425       for (y=0; y < (ssize_t) image->rows; y++)
2426       {
2427         MagickBooleanType
2428           sync;
2429
2430         register ssize_t
2431           x;
2432
2433         register Quantum
2434           *restrict q;
2435
2436         if (status == MagickFalse)
2437           continue;
2438         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2439           exception);
2440         if (q == (Quantum *) NULL)
2441           {
2442             status=MagickFalse;
2443             continue;
2444           }
2445         for (x=0; x < (ssize_t) image->columns; x++)
2446         {
2447           double
2448             blue,
2449             chroma,
2450             green,
2451             hue,
2452             luma,
2453             red;
2454
2455           hue=(double) (QuantumScale*GetPixelRed(image,q));
2456           chroma=(double) (QuantumScale*GetPixelGreen(image,q));
2457           luma=(double) (QuantumScale*GetPixelBlue(image,q));
2458           ConvertHCLToRGB(hue,chroma,luma,&red,&green,&blue);
2459           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2460           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2461           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2462           q+=GetPixelChannels(image);
2463         }
2464         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2465         if (sync == MagickFalse)
2466           status=MagickFalse;
2467       }
2468       image_view=DestroyCacheView(image_view);
2469       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2470         return(MagickFalse);
2471       return(status);
2472     }
2473     case HSBColorspace:
2474     {
2475       /*
2476         Transform image from HSB to sRGB.
2477       */
2478       if (image->storage_class == PseudoClass)
2479         {
2480           if (SyncImage(image,exception) == MagickFalse)
2481             return(MagickFalse);
2482           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2483             return(MagickFalse);
2484         }
2485       image_view=AcquireAuthenticCacheView(image,exception);
2486 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2487       #pragma omp parallel for schedule(static,4) shared(status) \
2488         dynamic_number_threads(image,image->columns,image->rows,1)
2489 #endif
2490       for (y=0; y < (ssize_t) image->rows; y++)
2491       {
2492         MagickBooleanType
2493           sync;
2494
2495         register ssize_t
2496           x;
2497
2498         register Quantum
2499           *restrict q;
2500
2501         if (status == MagickFalse)
2502           continue;
2503         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2504           exception);
2505         if (q == (Quantum *) NULL)
2506           {
2507             status=MagickFalse;
2508             continue;
2509           }
2510         for (x=0; x < (ssize_t) image->columns; x++)
2511         {
2512           double
2513             blue,
2514             brightness,
2515             green,
2516             hue,
2517             red,
2518             saturation;
2519
2520           hue=(double) (QuantumScale*GetPixelRed(image,q));
2521           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
2522           brightness=(double) (QuantumScale*GetPixelBlue(image,q));
2523           ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
2524           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2525           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2526           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2527           q+=GetPixelChannels(image);
2528         }
2529         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2530         if (sync == MagickFalse)
2531           status=MagickFalse;
2532       }
2533       image_view=DestroyCacheView(image_view);
2534       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2535         return(MagickFalse);
2536       return(status);
2537     }
2538     case HSLColorspace:
2539     {
2540       /*
2541         Transform image from HSL to sRGB.
2542       */
2543       if (image->storage_class == PseudoClass)
2544         {
2545           if (SyncImage(image,exception) == MagickFalse)
2546             return(MagickFalse);
2547           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2548             return(MagickFalse);
2549         }
2550       image_view=AcquireAuthenticCacheView(image,exception);
2551 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2552       #pragma omp parallel for schedule(static,4) shared(status) \
2553         dynamic_number_threads(image,image->columns,image->rows,1)
2554 #endif
2555       for (y=0; y < (ssize_t) image->rows; y++)
2556       {
2557         MagickBooleanType
2558           sync;
2559
2560         register ssize_t
2561           x;
2562
2563         register Quantum
2564           *restrict q;
2565
2566         if (status == MagickFalse)
2567           continue;
2568         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2569           exception);
2570         if (q == (Quantum *) NULL)
2571           {
2572             status=MagickFalse;
2573             continue;
2574           }
2575         for (x=0; x < (ssize_t) image->columns; x++)
2576         {
2577           double
2578             blue,
2579             green,
2580             hue,
2581             lightness,
2582             red,
2583             saturation;
2584
2585           hue=(double) (QuantumScale*GetPixelRed(image,q));
2586           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
2587           lightness=(double) (QuantumScale*GetPixelBlue(image,q));
2588           ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
2589           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2590           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2591           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2592           q+=GetPixelChannels(image);
2593         }
2594         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2595         if (sync == MagickFalse)
2596           status=MagickFalse;
2597       }
2598       image_view=DestroyCacheView(image_view);
2599       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2600         return(MagickFalse);
2601       return(status);
2602     }
2603     case HWBColorspace:
2604     {
2605       /*
2606         Transform image from HWB to sRGB.
2607       */
2608       if (image->storage_class == PseudoClass)
2609         {
2610           if (SyncImage(image,exception) == MagickFalse)
2611             return(MagickFalse);
2612           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2613             return(MagickFalse);
2614         }
2615       image_view=AcquireAuthenticCacheView(image,exception);
2616 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2617       #pragma omp parallel for schedule(static,4) shared(status) \
2618         dynamic_number_threads(image,image->columns,image->rows,1)
2619 #endif
2620       for (y=0; y < (ssize_t) image->rows; y++)
2621       {
2622         MagickBooleanType
2623           sync;
2624
2625         register ssize_t
2626           x;
2627
2628         register Quantum
2629           *restrict q;
2630
2631         if (status == MagickFalse)
2632           continue;
2633         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2634           exception);
2635         if (q == (Quantum *) NULL)
2636           {
2637             status=MagickFalse;
2638             continue;
2639           }
2640         for (x=0; x < (ssize_t) image->columns; x++)
2641         {
2642           double
2643             blackness,
2644             blue,
2645             green,
2646             hue,
2647             red,
2648             whiteness;
2649
2650           hue=(double) (QuantumScale*GetPixelRed(image,q));
2651           whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
2652           blackness=(double) (QuantumScale*GetPixelBlue(image,q));
2653           ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
2654           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2655           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2656           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2657           q+=GetPixelChannels(image);
2658         }
2659         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2660         if (sync == MagickFalse)
2661           status=MagickFalse;
2662       }
2663       image_view=DestroyCacheView(image_view);
2664       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2665         return(MagickFalse);
2666       return(status);
2667     }
2668     case LabColorspace:
2669     {
2670       /*
2671         Transform image from Lab to sRGB.
2672       */
2673       if (image->storage_class == PseudoClass)
2674         {
2675           if (SyncImage(image,exception) == MagickFalse)
2676             return(MagickFalse);
2677           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2678             return(MagickFalse);
2679         }
2680       image_view=AcquireAuthenticCacheView(image,exception);
2681 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2682       #pragma omp parallel for schedule(static,4) shared(status) \
2683         dynamic_number_threads(image,image->columns,image->rows,1)
2684 #endif
2685       for (y=0; y < (ssize_t) image->rows; y++)
2686       {
2687         MagickBooleanType
2688           sync;
2689
2690         register ssize_t
2691           x;
2692
2693         register Quantum
2694           *restrict q;
2695
2696         if (status == MagickFalse)
2697           continue;
2698         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2699           exception);
2700         if (q == (Quantum *) NULL)
2701           {
2702             status=MagickFalse;
2703             continue;
2704           }
2705         for (x=0; x < (ssize_t) image->columns; x++)
2706         {
2707           double
2708             a,
2709             b,
2710             blue,
2711             green,
2712             L,
2713             red,
2714             X,
2715             Y,
2716             Z;
2717
2718           L=QuantumScale*GetPixelRed(image,q);
2719           a=QuantumScale*GetPixelGreen(image,q);
2720           b=QuantumScale*GetPixelBlue(image,q);
2721           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2722           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2723           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2724           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2725           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2726           q+=GetPixelChannels(image);
2727         }
2728         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2729         if (sync == MagickFalse)
2730           status=MagickFalse;
2731       }
2732       image_view=DestroyCacheView(image_view);
2733       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2734         return(MagickFalse);
2735       return(status);
2736     }
2737     case LCHColorspace:
2738     {
2739       /*
2740         Transform image from LCH to sRGB.
2741       */
2742       if (image->storage_class == PseudoClass)
2743         {
2744           if (SyncImage(image,exception) == MagickFalse)
2745             return(MagickFalse);
2746           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2747             return(MagickFalse);
2748         }
2749       image_view=AcquireAuthenticCacheView(image,exception);
2750 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2751       #pragma omp parallel for schedule(static,4) shared(status) \
2752         dynamic_number_threads(image,image->columns,image->rows,1)
2753 #endif
2754       for (y=0; y < (ssize_t) image->rows; y++)
2755       {
2756         MagickBooleanType
2757           sync;
2758
2759         register ssize_t
2760           x;
2761
2762         register Quantum
2763           *restrict q;
2764
2765         if (status == MagickFalse)
2766           continue;
2767         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2768           exception);
2769         if (q == (Quantum *) NULL)
2770           {
2771             status=MagickFalse;
2772             continue;
2773           }
2774         for (x=0; x < (ssize_t) image->columns; x++)
2775         {
2776           double
2777             a,
2778             b,
2779             blue,
2780             C,
2781             green,
2782             H,
2783             L,
2784             red,
2785             X,
2786             Y,
2787             Z;
2788
2789           L=QuantumScale*GetPixelRed(image,q);
2790           C=QuantumScale*GetPixelGreen(image,q);
2791           H=QuantumScale*GetPixelBlue(image,q);
2792           a=C*cos(H*(MagickPI/180.0));
2793           b=C*sin(H*(MagickPI/180.0));
2794           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2795           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2796           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2797           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2798           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2799           q+=GetPixelChannels(image);
2800         }
2801         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2802         if (sync == MagickFalse)
2803           status=MagickFalse;
2804       }
2805       image_view=DestroyCacheView(image_view);
2806       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2807         return(MagickFalse);
2808       return(status);
2809     }
2810     case LMSColorspace:
2811     {
2812       /*
2813         Transform image from LMS to sRGB.
2814       */
2815       if (image->storage_class == PseudoClass)
2816         {
2817           if (SyncImage(image,exception) == MagickFalse)
2818             return(MagickFalse);
2819           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2820             return(MagickFalse);
2821         }
2822       image_view=AcquireAuthenticCacheView(image,exception);
2823 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2824       #pragma omp parallel for schedule(static,4) shared(status) \
2825         dynamic_number_threads(image,image->columns,image->rows,1)
2826 #endif
2827       for (y=0; y < (ssize_t) image->rows; y++)
2828       {
2829         MagickBooleanType
2830           sync;
2831
2832         register ssize_t
2833           x;
2834
2835         register Quantum
2836           *restrict q;
2837
2838         if (status == MagickFalse)
2839           continue;
2840         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2841           exception);
2842         if (q == (Quantum *) NULL)
2843           {
2844             status=MagickFalse;
2845             continue;
2846           }
2847         for (x=0; x < (ssize_t) image->columns; x++)
2848         {
2849           double
2850             blue,
2851             green,
2852             L,
2853             M,
2854             red,
2855             S,
2856             X,
2857             Y,
2858             Z;
2859
2860           L=QuantumScale*GetPixelRed(image,q);
2861           M=QuantumScale*GetPixelGreen(image,q);
2862           S=QuantumScale*GetPixelBlue(image,q);
2863           ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
2864           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2865           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2866           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2867           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2868           q+=GetPixelChannels(image);
2869         }
2870         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2871         if (sync == MagickFalse)
2872           status=MagickFalse;
2873       }
2874       image_view=DestroyCacheView(image_view);
2875       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2876         return(MagickFalse);
2877       return(status);
2878     }
2879     case LogColorspace:
2880     {
2881       const char
2882         *value;
2883
2884       double
2885         black,
2886         density,
2887         film_gamma,
2888         gamma,
2889         reference_black,
2890         reference_white;
2891
2892       Quantum
2893         *logmap;
2894
2895       /*
2896         Transform Log to sRGB colorspace.
2897       */
2898       density=DisplayGamma;
2899       gamma=DisplayGamma;
2900       value=GetImageProperty(image,"gamma",exception);
2901       if (value != (const char *) NULL)
2902         gamma=MagickEpsilonReciprocal(StringToDouble(value,(char **) NULL));
2903       film_gamma=FilmGamma;
2904       value=GetImageProperty(image,"film-gamma",exception);
2905       if (value != (const char *) NULL)
2906         film_gamma=StringToDouble(value,(char **) NULL);
2907       reference_black=ReferenceBlack;
2908       value=GetImageProperty(image,"reference-black",exception);
2909       if (value != (const char *) NULL)
2910         reference_black=StringToDouble(value,(char **) NULL);
2911       reference_white=ReferenceWhite;
2912       value=GetImageProperty(image,"reference-white",exception);
2913       if (value != (const char *) NULL)
2914         reference_white=StringToDouble(value,(char **) NULL);
2915       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2916         sizeof(*logmap));
2917       if (logmap == (Quantum *) NULL)
2918         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2919           image->filename);
2920       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
2921         0.002/film_gamma);
2922       for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
2923         logmap[i]=(Quantum) 0;
2924       for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
2925         logmap[i]=ClampToQuantum(QuantumRange/(1.0-black)*
2926           (pow(10.0,(1024.0*i/MaxMap-reference_white)*
2927           (gamma/density)*0.002/film_gamma)-black));
2928       for ( ; i <= (ssize_t) MaxMap; i++)
2929         logmap[i]=QuantumRange;
2930       if (image->storage_class == PseudoClass)
2931         {
2932           if (SyncImage(image,exception) == MagickFalse)
2933             return(MagickFalse);
2934           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2935             return(MagickFalse);
2936         }
2937       image_view=AcquireAuthenticCacheView(image,exception);
2938 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2939       #pragma omp parallel for schedule(static,4) shared(status) \
2940         dynamic_number_threads(image,image->columns,image->rows,1)
2941 #endif
2942       for (y=0; y < (ssize_t) image->rows; y++)
2943       {
2944         MagickBooleanType
2945           sync;
2946
2947         register ssize_t
2948           x;
2949
2950         register Quantum
2951           *restrict q;
2952
2953         if (status == MagickFalse)
2954           continue;
2955         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2956           exception);
2957         if (q == (Quantum *) NULL)
2958           {
2959             status=MagickFalse;
2960             continue;
2961           }
2962         for (x=(ssize_t) image->columns; x != 0; x--)
2963         {
2964           double
2965             blue,
2966             green,
2967             red;
2968
2969           red=sRGBCompandor((double) logmap[ScaleQuantumToMap(
2970             GetPixelRed(image,q))]);
2971           green=sRGBCompandor((double) logmap[ScaleQuantumToMap(
2972             GetPixelGreen(image,q))]);
2973           blue=sRGBCompandor((double) logmap[ScaleQuantumToMap(
2974             GetPixelBlue(image,q))]);
2975           SetPixelRed(image,ClampToQuantum(red),q);
2976           SetPixelGreen(image,ClampToQuantum(green),q);
2977           SetPixelBlue(image,ClampToQuantum(blue),q);
2978           q+=GetPixelChannels(image);
2979         }
2980         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2981         if (sync == MagickFalse)
2982           status=MagickFalse;
2983       }
2984       image_view=DestroyCacheView(image_view);
2985       logmap=(Quantum *) RelinquishMagickMemory(logmap);
2986       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2987         return(MagickFalse);
2988       return(status);
2989     }
2990     case LuvColorspace:
2991     {
2992       /*
2993         Transform image from Luv to sRGB.
2994       */
2995       if (image->storage_class == PseudoClass)
2996         {
2997           if (SyncImage(image,exception) == MagickFalse)
2998             return(MagickFalse);
2999           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3000             return(MagickFalse);
3001         }
3002       image_view=AcquireAuthenticCacheView(image,exception);
3003 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3004       #pragma omp parallel for schedule(static,4) shared(status) \
3005         dynamic_number_threads(image,image->columns,image->rows,1)
3006 #endif
3007       for (y=0; y < (ssize_t) image->rows; y++)
3008       {
3009         MagickBooleanType
3010           sync;
3011
3012         register ssize_t
3013           x;
3014
3015         register Quantum
3016           *restrict q;
3017
3018         if (status == MagickFalse)
3019           continue;
3020         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3021           exception);
3022         if (q == (Quantum *) NULL)
3023           {
3024             status=MagickFalse;
3025             continue;
3026           }
3027         for (x=0; x < (ssize_t) image->columns; x++)
3028         {
3029           double
3030             blue,
3031             green,
3032             L,
3033             red,
3034             u,
3035             v,
3036             X,
3037             Y,
3038             Z;
3039
3040           L=QuantumScale*GetPixelRed(image,q);
3041           u=QuantumScale*GetPixelGreen(image,q);
3042           v=QuantumScale*GetPixelBlue(image,q);
3043           ConvertLuvToXYZ(L,u,v,&X,&Y,&Z);
3044           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
3045           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
3046           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
3047           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
3048           q+=GetPixelChannels(image);
3049         }
3050         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3051         if (sync == MagickFalse)
3052           status=MagickFalse;
3053       }
3054       image_view=DestroyCacheView(image_view);
3055       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3056         return(MagickFalse);
3057       return(status);
3058     }
3059     case RGBColorspace:
3060     {
3061       /*
3062         Transform linear RGB to sRGB colorspace.
3063       */
3064       if (image->storage_class == PseudoClass)
3065         {
3066           if (SyncImage(image,exception) == MagickFalse)
3067             return(MagickFalse);
3068           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3069             return(MagickFalse);
3070         }
3071       image_view=AcquireAuthenticCacheView(image,exception);
3072 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3073       #pragma omp parallel for schedule(static,4) shared(status) \
3074         dynamic_number_threads(image,image->columns,image->rows,1)
3075 #endif
3076       for (y=0; y < (ssize_t) image->rows; y++)
3077       {
3078         MagickBooleanType
3079           sync;
3080
3081         register ssize_t
3082           x;
3083
3084         register Quantum
3085           *restrict q;
3086
3087         if (status == MagickFalse)
3088           continue;
3089         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3090           exception);
3091         if (q == (Quantum *) NULL)
3092           {
3093             status=MagickFalse;
3094             continue;
3095           }
3096         for (x=(ssize_t) image->columns; x != 0; x--)
3097         {
3098           double
3099             blue,
3100             green,
3101             red;
3102
3103           red=sRGBCompandor((double) GetPixelRed(image,q));
3104           green=sRGBCompandor((double) GetPixelGreen(image,q));
3105           blue=sRGBCompandor((double) GetPixelBlue(image,q));
3106           SetPixelRed(image,ClampToQuantum(red),q);
3107           SetPixelGreen(image,ClampToQuantum(green),q);
3108           SetPixelBlue(image,ClampToQuantum(blue),q);
3109           q+=GetPixelChannels(image);
3110         }
3111         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3112         if (sync == MagickFalse)
3113           status=MagickFalse;
3114       }
3115       image_view=DestroyCacheView(image_view);
3116       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3117         return(MagickFalse);
3118       return(status);
3119     }
3120     case XYZColorspace:
3121     {
3122       /*
3123         Transform image from XYZ to sRGB.
3124       */
3125       if (image->storage_class == PseudoClass)
3126         {
3127           if (SyncImage(image,exception) == MagickFalse)
3128             return(MagickFalse);
3129           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3130             return(MagickFalse);
3131         }
3132       image_view=AcquireAuthenticCacheView(image,exception);
3133 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3134       #pragma omp parallel for schedule(static,4) shared(status) \
3135         dynamic_number_threads(image,image->columns,image->rows,1)
3136 #endif
3137       for (y=0; y < (ssize_t) image->rows; y++)
3138       {
3139         MagickBooleanType
3140           sync;
3141
3142         register ssize_t
3143           x;
3144
3145         register Quantum
3146           *restrict q;
3147
3148         if (status == MagickFalse)
3149           continue;
3150         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3151           exception);
3152         if (q == (Quantum *) NULL)
3153           {
3154             status=MagickFalse;
3155             continue;
3156           }
3157         for (x=0; x < (ssize_t) image->columns; x++)
3158         {
3159           double
3160             blue,
3161             green,
3162             red,
3163             X,
3164             Y,
3165             Z;
3166
3167           X=QuantumScale*GetPixelRed(image,q);
3168           Y=QuantumScale*GetPixelGreen(image,q);
3169           Z=QuantumScale*GetPixelBlue(image,q);
3170           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
3171           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
3172           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
3173           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
3174           q+=GetPixelChannels(image);
3175         }
3176         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3177         if (sync == MagickFalse)
3178           status=MagickFalse;
3179       }
3180       image_view=DestroyCacheView(image_view);
3181       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3182         return(MagickFalse);
3183       return(status);
3184     }
3185     default:
3186       break;
3187   }
3188   /*
3189     Allocate the tables.
3190   */
3191   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3192     sizeof(*x_map));
3193   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3194     sizeof(*y_map));
3195   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3196     sizeof(*z_map));
3197   if ((x_map == (TransformPacket *) NULL) ||
3198       (y_map == (TransformPacket *) NULL) ||
3199       (z_map == (TransformPacket *) NULL))
3200     {
3201       if (z_map != (TransformPacket *) NULL)
3202         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
3203       if (y_map != (TransformPacket *) NULL)
3204         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
3205       if (x_map != (TransformPacket *) NULL)
3206         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
3207       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3208         image->filename);
3209     }
3210   switch (image->colorspace)
3211   {
3212     case OHTAColorspace:
3213     {
3214       /*
3215         Initialize OHTA tables:
3216
3217           R = I1+1.00000*I2-0.66668*I3
3218           G = I1+0.00000*I2+1.33333*I3
3219           B = I1-1.00000*I2-0.66668*I3
3220
3221         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
3222         through QuantumRange.
3223       */
3224 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3225       #pragma omp parallel for schedule(static) \
3226         dynamic_number_threads(image,image->columns,1,1)
3227 #endif
3228       for (i=0; i <= (ssize_t) MaxMap; i++)
3229       {
3230         x_map[i].x=1.0*i;
3231         y_map[i].x=0.5*(2.0*i-MaxMap);
3232         z_map[i].x=(-0.333340)*(2.0*i-MaxMap);
3233         x_map[i].y=1.0*i;
3234         y_map[i].y=0.000000;
3235         z_map[i].y=0.666665*(2.0*i-MaxMap);
3236         x_map[i].z=1.0*i;
3237         y_map[i].z=(-0.500000)*(2.0*i-MaxMap);
3238         z_map[i].z=(-0.333340)*(2.0*i-MaxMap);
3239       }
3240       break;
3241     }
3242     case Rec601YCbCrColorspace:
3243     case YCbCrColorspace:
3244     {
3245       /*
3246         Initialize YCbCr tables:
3247
3248           R = Y            +1.402000*Cr
3249           G = Y-0.344136*Cb-0.714136*Cr
3250           B = Y+1.772000*Cb
3251
3252         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
3253         through QuantumRange.
3254       */
3255 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3256       #pragma omp parallel for schedule(static) \
3257         dynamic_number_threads(image,image->columns,1,1)
3258 #endif
3259       for (i=0; i <= (ssize_t) MaxMap; i++)
3260       {
3261         x_map[i].x=0.99999999999914679361*i;
3262         y_map[i].x=(1.2188941887145875e-06)*i;
3263         z_map[i].x=0.5*1.4019995886561440468*(2.00*i-MaxMap);
3264         x_map[i].y=0.99999975910502514331*i;
3265         y_map[i].y=0.5*(-0.34413567816504303521)*(2.00*i-MaxMap);
3266         z_map[i].y=0.5*(-0.71413649331646789076)*(2.00*i-MaxMap);
3267         x_map[i].z=1.00000124040004623180*i;
3268         y_map[i].z=0.5*1.77200006607230409200*(2.00*i-MaxMap);
3269         z_map[i].z=2.1453384174593273e-06*i;
3270       }
3271       break;
3272     }
3273     case Rec709YCbCrColorspace:
3274     {
3275       /*
3276         Initialize YCbCr tables:
3277
3278           R = Y            +1.574800*Cr
3279           G = Y-0.187324*Cb-0.468124*Cr
3280           B = Y+1.855600*Cb
3281
3282         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
3283         through QuantumRange.
3284       */
3285 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3286       #pragma omp parallel for schedule(static) \
3287         dynamic_number_threads(image,image->columns,1,1)
3288 #endif
3289       for (i=0; i <= (ssize_t) MaxMap; i++)
3290       {
3291         x_map[i].x=1.0*i;
3292         y_map[i].x=0.000000*(2.0*i-MaxMap);
3293         z_map[i].x=0.5*1.574800*(2.0*i-MaxMap);
3294         x_map[i].y=1.0*i;
3295         y_map[i].y=0.5*(-0.187324)*(2.0*i-MaxMap);
3296         z_map[i].y=0.5*(-0.468124)*(2.0*i-MaxMap);
3297         x_map[i].z=1.0*i;
3298         y_map[i].z=0.5*1.855600*(2.0*i-MaxMap);
3299         z_map[i].z=0.000000*(2.0*i-MaxMap);
3300       }
3301       break;
3302     }
3303     case YCCColorspace:
3304     {
3305       /*
3306         Initialize YCC tables:
3307
3308           R = Y            +1.340762*C2
3309           G = Y-0.317038*C1-0.682243*C2
3310           B = Y+1.632639*C1
3311
3312         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
3313       */
3314 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3315       #pragma omp parallel for schedule(static) \
3316         dynamic_number_threads(image,image->columns,1,1)
3317 #endif
3318       for (i=0; i <= (ssize_t) MaxMap; i++)
3319       {
3320         x_map[i].x=1.3584000*i;
3321         y_map[i].x=0.0000000;
3322         z_map[i].x=1.8215000*(1.0*i-(double)
3323           ScaleQuantumToMap(ScaleCharToQuantum(137)));
3324         x_map[i].y=1.3584000*i;
3325         y_map[i].y=(-0.4302726)*(1.0*i-(double)
3326           ScaleQuantumToMap(ScaleCharToQuantum(156)));
3327         z_map[i].y=(-0.9271435)*(1.0*i-(double)
3328           ScaleQuantumToMap(ScaleCharToQuantum(137)));
3329         x_map[i].z=1.3584000*i;
3330         y_map[i].z=2.2179000*(1.0*i-(double)
3331           ScaleQuantumToMap(ScaleCharToQuantum(156)));
3332         z_map[i].z=0.0000000;
3333       }
3334       break;
3335     }
3336     case YIQColorspace:
3337     {
3338       /*
3339         Initialize YIQ tables:
3340
3341           R = Y+0.95620*I+0.62140*Q
3342           G = Y-0.27270*I-0.64680*Q
3343           B = Y-1.10370*I+1.70060*Q
3344
3345         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
3346         through QuantumRange.
3347       */
3348 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3349       #pragma omp parallel for schedule(static) \
3350         dynamic_number_threads(image,image->columns,1,1)
3351 #endif
3352       for (i=0; i <= (ssize_t) MaxMap; i++)
3353       {
3354         x_map[i].x=1.0*i;
3355         y_map[i].x=0.5*0.9562957197589482261*(2.00000*i-MaxMap);
3356         z_map[i].x=0.5*0.6210244164652610754*(2.00000*i-MaxMap);
3357         x_map[i].y=1.0*i;
3358         y_map[i].y=0.5*(-0.2721220993185104464)*(2.00000*i-MaxMap);
3359         z_map[i].y=0.5*(-0.6473805968256950427)*(2.00000*i-MaxMap);
3360         x_map[i].z=1.0*i;
3361         y_map[i].z=0.5*(-1.1069890167364901945)*(2.00000*i-MaxMap);
3362         z_map[i].z=0.5*1.7046149983646481374*(2.00000*i-MaxMap);
3363       }
3364       break;
3365     }
3366     case YPbPrColorspace:
3367     {
3368       /*
3369         Initialize YPbPr tables:
3370
3371           R = Y            +1.402000*C2
3372           G = Y-0.344136*C1+0.714136*C2
3373           B = Y+1.772000*C1
3374
3375         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
3376         through QuantumRange.
3377       */
3378 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3379       #pragma omp parallel for schedule(static) \
3380         dynamic_number_threads(image,image->columns,1,1)
3381 #endif
3382       for (i=0; i <= (ssize_t) MaxMap; i++)
3383       {
3384         x_map[i].x=0.99999999999914679361*i;
3385         y_map[i].x=(-1.2188941887145875e-06)*(2.0*i-MaxMap);
3386         z_map[i].x=0.5*1.4019995886561440468*(2.0*i-MaxMap);
3387         x_map[i].y=0.99999975910502514331*i;
3388         y_map[i].y=0.5*(-0.34413567816504303521)*(2.0*i-MaxMap);
3389         z_map[i].y=0.5*(-0.71413649331646789076)*(2.0*i-MaxMap);
3390         x_map[i].z=1.00000124040004623180*i;
3391         y_map[i].z=0.5*1.77200006607230409200*(2.0*i-MaxMap);
3392         z_map[i].z=2.1453384174593273e-06*(2.0*i-MaxMap);
3393       }
3394       break;
3395     }
3396     case YUVColorspace:
3397     {
3398       /*
3399         Initialize YUV tables:
3400
3401           R = Y         +1.13983*V
3402           G = Y-0.39464*U-0.58060*V
3403           B = Y+2.03211*U
3404
3405         U and V, normally -0.5 through 0.5, must be normalized to the range 0
3406         through QuantumRange.
3407       */
3408 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3409       #pragma omp parallel for schedule(static) \
3410         dynamic_number_threads(image,image->columns,1,1)
3411 #endif
3412       for (i=0; i <= (ssize_t) MaxMap; i++)
3413       {
3414         x_map[i].x=1.0*i;
3415         y_map[i].x=(-3.945707070708279e-05)*(2.0*i-MaxMap);
3416         z_map[i].x=0.5*1.1398279671717170825*(2.0*i-MaxMap);
3417         x_map[i].y=1.0*i;
3418         y_map[i].y=0.5*(-0.3946101641414141437)*(2.0*i-MaxMap);
3419         z_map[i].y=0.5*(-0.5805003156565656797)*(2.0*i-MaxMap);
3420         x_map[i].z=1.0*i;
3421         y_map[i].z=0.5*2.0319996843434342537*(2.0*i-MaxMap);
3422         z_map[i].z=(-4.813762626262513e-04)*(2.0*i-MaxMap);
3423       }
3424       break;
3425     }
3426     default:
3427     {
3428       /*
3429         Linear conversion tables.
3430       */
3431 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3432       #pragma omp parallel for schedule(static) \
3433         dynamic_number_threads(image,image->columns,1,1)
3434 #endif
3435       for (i=0; i <= (ssize_t) MaxMap; i++)
3436       {
3437         x_map[i].x=1.0*i;
3438         y_map[i].x=0.0;
3439         z_map[i].x=0.0;
3440         x_map[i].y=0.0;
3441         y_map[i].y=1.0*i;
3442         z_map[i].y=0.0;
3443         x_map[i].z=0.0;
3444         y_map[i].z=0.0;
3445         z_map[i].z=1.0*i;
3446       }
3447       break;
3448     }
3449   }
3450   /*
3451     Convert to sRGB.
3452   */
3453   switch (image->storage_class)
3454   {
3455     case DirectClass:
3456     default:
3457     {
3458       /*
3459         Convert DirectClass image.
3460       */
3461       image_view=AcquireAuthenticCacheView(image,exception);
3462 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3463       #pragma omp parallel for schedule(static,4) shared(status) \
3464         dynamic_number_threads(image,image->columns,image->rows,1)
3465 #endif
3466       for (y=0; y < (ssize_t) image->rows; y++)
3467       {
3468         MagickBooleanType
3469           sync;
3470
3471         PixelInfo
3472           pixel;
3473
3474         register ssize_t
3475           x;
3476
3477         register Quantum
3478           *restrict q;
3479
3480         if (status == MagickFalse)
3481           continue;
3482         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3483           exception);
3484         if (q == (Quantum *) NULL)
3485           {
3486             status=MagickFalse;
3487             continue;
3488           }
3489         for (x=0; x < (ssize_t) image->columns; x++)
3490         {
3491           register size_t
3492             blue,
3493             green,
3494             red;
3495
3496           red=ScaleQuantumToMap(GetPixelRed(image,q));
3497           green=ScaleQuantumToMap(GetPixelGreen(image,q));
3498           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
3499           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
3500           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
3501           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
3502           if (colorspace == YCCColorspace)
3503             {
3504 #if !defined(MAGICKCORE_HDRI_SUPPORT)
3505               pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3506                 pixel.red)];
3507               pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3508                 pixel.green)];
3509               pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3510                 pixel.blue)];
3511 #endif
3512             }
3513           SetPixelRed(image,ClampToQuantum(sRGBCompandor((double)
3514             ScaleMapToQuantum(pixel.red))),q);
3515           SetPixelGreen(image,ClampToQuantum(sRGBCompandor((double)
3516             ScaleMapToQuantum(pixel.green))),q);
3517           SetPixelBlue(image,ClampToQuantum(sRGBCompandor((double)
3518             ScaleMapToQuantum(pixel.blue))),q);
3519           q+=GetPixelChannels(image);
3520         }
3521         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3522         if (sync == MagickFalse)
3523           status=MagickFalse;
3524         if (image->progress_monitor != (MagickProgressMonitor) NULL)
3525           {
3526             MagickBooleanType
3527               proceed;
3528
3529 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3530             #pragma omp critical (MagickCore_TransformsRGBImage)
3531 #endif
3532             proceed=SetImageProgress(image,TransformsRGBImageTag,progress++,
3533               image->rows);
3534             if (proceed == MagickFalse)
3535               status=MagickFalse;
3536           }
3537       }
3538       image_view=DestroyCacheView(image_view);
3539       break;
3540     }
3541     case PseudoClass:
3542     {
3543       /*
3544         Convert PseudoClass image.
3545       */
3546 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3547       #pragma omp parallel for schedule(static,4) shared(status) \
3548         dynamic_number_threads(image,image->columns,1,1)
3549 #endif
3550       for (i=0; i < (ssize_t) image->colors; i++)
3551       {
3552         PixelInfo
3553           pixel;
3554
3555         register size_t
3556           blue,
3557           green,
3558           red;
3559
3560         red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red));
3561         green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green));
3562         blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue));
3563         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
3564         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
3565         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
3566         if (colorspace == YCCColorspace)
3567           {
3568 #if !defined(MAGICKCORE_HDRI_SUPPORT)
3569             pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3570               pixel.red)];
3571             pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3572               pixel.green)];
3573             pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3574               pixel.blue)];
3575 #endif
3576           }
3577         image->colormap[i].red=(double) ClampToQuantum(
3578           sRGBCompandor((double) ScaleMapToQuantum(pixel.red)));
3579         image->colormap[i].green=(double) ClampToQuantum(
3580           sRGBCompandor((double) ScaleMapToQuantum(pixel.green)));
3581         image->colormap[i].blue=(double) ClampToQuantum(
3582           sRGBCompandor((double) ScaleMapToQuantum(pixel.blue)));
3583       }
3584       (void) SyncImage(image,exception);
3585       break;
3586     }
3587   }
3588   /*
3589     Relinquish resources.
3590   */
3591   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
3592   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
3593   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
3594   if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3595     return(MagickFalse);
3596   return(MagickTrue);
3597 }