]> 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) && !defined(NoBenefitFromParallelism)
969       #pragma omp parallel for schedule(static,4) \
970         dynamic_number_threads(image,image->columns,1,1)
971 #endif
972       for (i=0; i <= (ssize_t) MaxMap; i++)
973         logmap[i]=ScaleMapToQuantum((double) (MaxMap*(reference_white+
974           log10(black+(1.0*i/MaxMap)*(1.0-black))/((gamma/density)*
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) && !defined(NoBenefitFromParallelism)
1321       #pragma omp parallel for schedule(static,4) \
1322         dynamic_number_threads(image,image->columns,1,1)
1323 #endif
1324       for (i=0; i <= (ssize_t) MaxMap; i++)
1325       {
1326         x_map[i].x=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) && !defined(NoBenefitFromParallelism)
1354       #pragma omp parallel for schedule(static,4) \
1355         dynamic_number_threads(image,image->columns,1,1)
1356 #endif
1357       for (i=0; i <= (ssize_t) MaxMap; i++)
1358       {
1359         x_map[i].x=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) && !defined(NoBenefitFromParallelism)
1386       #pragma omp parallel for schedule(static,4) \
1387         dynamic_number_threads(image,image->columns,1,1)
1388 #endif
1389       for (i=0; i <= (ssize_t) MaxMap; i++)
1390       {
1391         x_map[i].x=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) && !defined(NoBenefitFromParallelism)
1457       #pragma omp parallel for schedule(static,4) \
1458         dynamic_number_threads(image,image->columns,1,1)
1459 #endif
1460       for (i=0; i <= (ssize_t) MaxMap; i++)
1461       {
1462         x_map[i].x=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) && !defined(NoBenefitFromParallelism)
1489       #pragma omp parallel for schedule(static,4) \
1490         dynamic_number_threads(image,image->columns,1,1)
1491 #endif
1492       for (i=0; i <= (ssize_t) MaxMap; i++)
1493       {
1494         x_map[i].x=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) && !defined(NoBenefitFromParallelism)
1521       #pragma omp parallel for schedule(static,4) \
1522         dynamic_number_threads(image,image->columns,1,1)
1523 #endif
1524       for (i=0; i <= (ssize_t) MaxMap; i++)
1525       {
1526         x_map[i].x=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) && !defined(NoBenefitFromParallelism)
1544       #pragma omp parallel for schedule(static,4) \
1545         dynamic_number_threads(image,image->columns,1,1)
1546 #endif
1547       for (i=0; i <= (ssize_t) MaxMap; i++)
1548       {
1549         x_map[i].x=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   static const float
1953     YCCMap[1389] =
1954     {
1955       0.000000f, 0.000720f, 0.001441f, 0.002161f, 0.002882f, 0.003602f,
1956       0.004323f, 0.005043f, 0.005764f, 0.006484f, 0.007205f, 0.007925f,
1957       0.008646f, 0.009366f, 0.010086f, 0.010807f, 0.011527f, 0.012248f,
1958       0.012968f, 0.013689f, 0.014409f, 0.015130f, 0.015850f, 0.016571f,
1959       0.017291f, 0.018012f, 0.018732f, 0.019452f, 0.020173f, 0.020893f,
1960       0.021614f, 0.022334f, 0.023055f, 0.023775f, 0.024496f, 0.025216f,
1961       0.025937f, 0.026657f, 0.027378f, 0.028098f, 0.028818f, 0.029539f,
1962       0.030259f, 0.030980f, 0.031700f, 0.032421f, 0.033141f, 0.033862f,
1963       0.034582f, 0.035303f, 0.036023f, 0.036744f, 0.037464f, 0.038184f,
1964       0.038905f, 0.039625f, 0.040346f, 0.041066f, 0.041787f, 0.042507f,
1965       0.043228f, 0.043948f, 0.044669f, 0.045389f, 0.046110f, 0.046830f,
1966       0.047550f, 0.048271f, 0.048991f, 0.049712f, 0.050432f, 0.051153f,
1967       0.051873f, 0.052594f, 0.053314f, 0.054035f, 0.054755f, 0.055476f,
1968       0.056196f, 0.056916f, 0.057637f, 0.058357f, 0.059078f, 0.059798f,
1969       0.060519f, 0.061239f, 0.061960f, 0.062680f, 0.063401f, 0.064121f,
1970       0.064842f, 0.065562f, 0.066282f, 0.067003f, 0.067723f, 0.068444f,
1971       0.069164f, 0.069885f, 0.070605f, 0.071326f, 0.072046f, 0.072767f,
1972       0.073487f, 0.074207f, 0.074928f, 0.075648f, 0.076369f, 0.077089f,
1973       0.077810f, 0.078530f, 0.079251f, 0.079971f, 0.080692f, 0.081412f,
1974       0.082133f, 0.082853f, 0.083573f, 0.084294f, 0.085014f, 0.085735f,
1975       0.086455f, 0.087176f, 0.087896f, 0.088617f, 0.089337f, 0.090058f,
1976       0.090778f, 0.091499f, 0.092219f, 0.092939f, 0.093660f, 0.094380f,
1977       0.095101f, 0.095821f, 0.096542f, 0.097262f, 0.097983f, 0.098703f,
1978       0.099424f, 0.100144f, 0.100865f, 0.101585f, 0.102305f, 0.103026f,
1979       0.103746f, 0.104467f, 0.105187f, 0.105908f, 0.106628f, 0.107349f,
1980       0.108069f, 0.108790f, 0.109510f, 0.110231f, 0.110951f, 0.111671f,
1981       0.112392f, 0.113112f, 0.113833f, 0.114553f, 0.115274f, 0.115994f,
1982       0.116715f, 0.117435f, 0.118156f, 0.118876f, 0.119597f, 0.120317f,
1983       0.121037f, 0.121758f, 0.122478f, 0.123199f, 0.123919f, 0.124640f,
1984       0.125360f, 0.126081f, 0.126801f, 0.127522f, 0.128242f, 0.128963f,
1985       0.129683f, 0.130403f, 0.131124f, 0.131844f, 0.132565f, 0.133285f,
1986       0.134006f, 0.134726f, 0.135447f, 0.136167f, 0.136888f, 0.137608f,
1987       0.138329f, 0.139049f, 0.139769f, 0.140490f, 0.141210f, 0.141931f,
1988       0.142651f, 0.143372f, 0.144092f, 0.144813f, 0.145533f, 0.146254f,
1989       0.146974f, 0.147695f, 0.148415f, 0.149135f, 0.149856f, 0.150576f,
1990       0.151297f, 0.152017f, 0.152738f, 0.153458f, 0.154179f, 0.154899f,
1991       0.155620f, 0.156340f, 0.157061f, 0.157781f, 0.158501f, 0.159222f,
1992       0.159942f, 0.160663f, 0.161383f, 0.162104f, 0.162824f, 0.163545f,
1993       0.164265f, 0.164986f, 0.165706f, 0.166427f, 0.167147f, 0.167867f,
1994       0.168588f, 0.169308f, 0.170029f, 0.170749f, 0.171470f, 0.172190f,
1995       0.172911f, 0.173631f, 0.174352f, 0.175072f, 0.175793f, 0.176513f,
1996       0.177233f, 0.177954f, 0.178674f, 0.179395f, 0.180115f, 0.180836f,
1997       0.181556f, 0.182277f, 0.182997f, 0.183718f, 0.184438f, 0.185159f,
1998       0.185879f, 0.186599f, 0.187320f, 0.188040f, 0.188761f, 0.189481f,
1999       0.190202f, 0.190922f, 0.191643f, 0.192363f, 0.193084f, 0.193804f,
2000       0.194524f, 0.195245f, 0.195965f, 0.196686f, 0.197406f, 0.198127f,
2001       0.198847f, 0.199568f, 0.200288f, 0.201009f, 0.201729f, 0.202450f,
2002       0.203170f, 0.203890f, 0.204611f, 0.205331f, 0.206052f, 0.206772f,
2003       0.207493f, 0.208213f, 0.208934f, 0.209654f, 0.210375f, 0.211095f,
2004       0.211816f, 0.212536f, 0.213256f, 0.213977f, 0.214697f, 0.215418f,
2005       0.216138f, 0.216859f, 0.217579f, 0.218300f, 0.219020f, 0.219741f,
2006       0.220461f, 0.221182f, 0.221902f, 0.222622f, 0.223343f, 0.224063f,
2007       0.224784f, 0.225504f, 0.226225f, 0.226945f, 0.227666f, 0.228386f,
2008       0.229107f, 0.229827f, 0.230548f, 0.231268f, 0.231988f, 0.232709f,
2009       0.233429f, 0.234150f, 0.234870f, 0.235591f, 0.236311f, 0.237032f,
2010       0.237752f, 0.238473f, 0.239193f, 0.239914f, 0.240634f, 0.241354f,
2011       0.242075f, 0.242795f, 0.243516f, 0.244236f, 0.244957f, 0.245677f,
2012       0.246398f, 0.247118f, 0.247839f, 0.248559f, 0.249280f, 0.250000f,
2013       0.250720f, 0.251441f, 0.252161f, 0.252882f, 0.253602f, 0.254323f,
2014       0.255043f, 0.255764f, 0.256484f, 0.257205f, 0.257925f, 0.258646f,
2015       0.259366f, 0.260086f, 0.260807f, 0.261527f, 0.262248f, 0.262968f,
2016       0.263689f, 0.264409f, 0.265130f, 0.265850f, 0.266571f, 0.267291f,
2017       0.268012f, 0.268732f, 0.269452f, 0.270173f, 0.270893f, 0.271614f,
2018       0.272334f, 0.273055f, 0.273775f, 0.274496f, 0.275216f, 0.275937f,
2019       0.276657f, 0.277378f, 0.278098f, 0.278818f, 0.279539f, 0.280259f,
2020       0.280980f, 0.281700f, 0.282421f, 0.283141f, 0.283862f, 0.284582f,
2021       0.285303f, 0.286023f, 0.286744f, 0.287464f, 0.288184f, 0.288905f,
2022       0.289625f, 0.290346f, 0.291066f, 0.291787f, 0.292507f, 0.293228f,
2023       0.293948f, 0.294669f, 0.295389f, 0.296109f, 0.296830f, 0.297550f,
2024       0.298271f, 0.298991f, 0.299712f, 0.300432f, 0.301153f, 0.301873f,
2025       0.302594f, 0.303314f, 0.304035f, 0.304755f, 0.305476f, 0.306196f,
2026       0.306916f, 0.307637f, 0.308357f, 0.309078f, 0.309798f, 0.310519f,
2027       0.311239f, 0.311960f, 0.312680f, 0.313401f, 0.314121f, 0.314842f,
2028       0.315562f, 0.316282f, 0.317003f, 0.317723f, 0.318444f, 0.319164f,
2029       0.319885f, 0.320605f, 0.321326f, 0.322046f, 0.322767f, 0.323487f,
2030       0.324207f, 0.324928f, 0.325648f, 0.326369f, 0.327089f, 0.327810f,
2031       0.328530f, 0.329251f, 0.329971f, 0.330692f, 0.331412f, 0.332133f,
2032       0.332853f, 0.333573f, 0.334294f, 0.335014f, 0.335735f, 0.336455f,
2033       0.337176f, 0.337896f, 0.338617f, 0.339337f, 0.340058f, 0.340778f,
2034       0.341499f, 0.342219f, 0.342939f, 0.343660f, 0.344380f, 0.345101f,
2035       0.345821f, 0.346542f, 0.347262f, 0.347983f, 0.348703f, 0.349424f,
2036       0.350144f, 0.350865f, 0.351585f, 0.352305f, 0.353026f, 0.353746f,
2037       0.354467f, 0.355187f, 0.355908f, 0.356628f, 0.357349f, 0.358069f,
2038       0.358790f, 0.359510f, 0.360231f, 0.360951f, 0.361671f, 0.362392f,
2039       0.363112f, 0.363833f, 0.364553f, 0.365274f, 0.365994f, 0.366715f,
2040       0.367435f, 0.368156f, 0.368876f, 0.369597f, 0.370317f, 0.371037f,
2041       0.371758f, 0.372478f, 0.373199f, 0.373919f, 0.374640f, 0.375360f,
2042       0.376081f, 0.376801f, 0.377522f, 0.378242f, 0.378963f, 0.379683f,
2043       0.380403f, 0.381124f, 0.381844f, 0.382565f, 0.383285f, 0.384006f,
2044       0.384726f, 0.385447f, 0.386167f, 0.386888f, 0.387608f, 0.388329f,
2045       0.389049f, 0.389769f, 0.390490f, 0.391210f, 0.391931f, 0.392651f,
2046       0.393372f, 0.394092f, 0.394813f, 0.395533f, 0.396254f, 0.396974f,
2047       0.397695f, 0.398415f, 0.399135f, 0.399856f, 0.400576f, 0.401297f,
2048       0.402017f, 0.402738f, 0.403458f, 0.404179f, 0.404899f, 0.405620f,
2049       0.406340f, 0.407061f, 0.407781f, 0.408501f, 0.409222f, 0.409942f,
2050       0.410663f, 0.411383f, 0.412104f, 0.412824f, 0.413545f, 0.414265f,
2051       0.414986f, 0.415706f, 0.416427f, 0.417147f, 0.417867f, 0.418588f,
2052       0.419308f, 0.420029f, 0.420749f, 0.421470f, 0.422190f, 0.422911f,
2053       0.423631f, 0.424352f, 0.425072f, 0.425793f, 0.426513f, 0.427233f,
2054       0.427954f, 0.428674f, 0.429395f, 0.430115f, 0.430836f, 0.431556f,
2055       0.432277f, 0.432997f, 0.433718f, 0.434438f, 0.435158f, 0.435879f,
2056       0.436599f, 0.437320f, 0.438040f, 0.438761f, 0.439481f, 0.440202f,
2057       0.440922f, 0.441643f, 0.442363f, 0.443084f, 0.443804f, 0.444524f,
2058       0.445245f, 0.445965f, 0.446686f, 0.447406f, 0.448127f, 0.448847f,
2059       0.449568f, 0.450288f, 0.451009f, 0.451729f, 0.452450f, 0.453170f,
2060       0.453891f, 0.454611f, 0.455331f, 0.456052f, 0.456772f, 0.457493f,
2061       0.458213f, 0.458934f, 0.459654f, 0.460375f, 0.461095f, 0.461816f,
2062       0.462536f, 0.463256f, 0.463977f, 0.464697f, 0.465418f, 0.466138f,
2063       0.466859f, 0.467579f, 0.468300f, 0.469020f, 0.469741f, 0.470461f,
2064       0.471182f, 0.471902f, 0.472622f, 0.473343f, 0.474063f, 0.474784f,
2065       0.475504f, 0.476225f, 0.476945f, 0.477666f, 0.478386f, 0.479107f,
2066       0.479827f, 0.480548f, 0.481268f, 0.481988f, 0.482709f, 0.483429f,
2067       0.484150f, 0.484870f, 0.485591f, 0.486311f, 0.487032f, 0.487752f,
2068       0.488473f, 0.489193f, 0.489914f, 0.490634f, 0.491354f, 0.492075f,
2069       0.492795f, 0.493516f, 0.494236f, 0.494957f, 0.495677f, 0.496398f,
2070       0.497118f, 0.497839f, 0.498559f, 0.499280f, 0.500000f, 0.500720f,
2071       0.501441f, 0.502161f, 0.502882f, 0.503602f, 0.504323f, 0.505043f,
2072       0.505764f, 0.506484f, 0.507205f, 0.507925f, 0.508646f, 0.509366f,
2073       0.510086f, 0.510807f, 0.511527f, 0.512248f, 0.512968f, 0.513689f,
2074       0.514409f, 0.515130f, 0.515850f, 0.516571f, 0.517291f, 0.518012f,
2075       0.518732f, 0.519452f, 0.520173f, 0.520893f, 0.521614f, 0.522334f,
2076       0.523055f, 0.523775f, 0.524496f, 0.525216f, 0.525937f, 0.526657f,
2077       0.527378f, 0.528098f, 0.528818f, 0.529539f, 0.530259f, 0.530980f,
2078       0.531700f, 0.532421f, 0.533141f, 0.533862f, 0.534582f, 0.535303f,
2079       0.536023f, 0.536744f, 0.537464f, 0.538184f, 0.538905f, 0.539625f,
2080       0.540346f, 0.541066f, 0.541787f, 0.542507f, 0.543228f, 0.543948f,
2081       0.544669f, 0.545389f, 0.546109f, 0.546830f, 0.547550f, 0.548271f,
2082       0.548991f, 0.549712f, 0.550432f, 0.551153f, 0.551873f, 0.552594f,
2083       0.553314f, 0.554035f, 0.554755f, 0.555476f, 0.556196f, 0.556916f,
2084       0.557637f, 0.558357f, 0.559078f, 0.559798f, 0.560519f, 0.561239f,
2085       0.561960f, 0.562680f, 0.563401f, 0.564121f, 0.564842f, 0.565562f,
2086       0.566282f, 0.567003f, 0.567723f, 0.568444f, 0.569164f, 0.569885f,
2087       0.570605f, 0.571326f, 0.572046f, 0.572767f, 0.573487f, 0.574207f,
2088       0.574928f, 0.575648f, 0.576369f, 0.577089f, 0.577810f, 0.578530f,
2089       0.579251f, 0.579971f, 0.580692f, 0.581412f, 0.582133f, 0.582853f,
2090       0.583573f, 0.584294f, 0.585014f, 0.585735f, 0.586455f, 0.587176f,
2091       0.587896f, 0.588617f, 0.589337f, 0.590058f, 0.590778f, 0.591499f,
2092       0.592219f, 0.592939f, 0.593660f, 0.594380f, 0.595101f, 0.595821f,
2093       0.596542f, 0.597262f, 0.597983f, 0.598703f, 0.599424f, 0.600144f,
2094       0.600865f, 0.601585f, 0.602305f, 0.603026f, 0.603746f, 0.604467f,
2095       0.605187f, 0.605908f, 0.606628f, 0.607349f, 0.608069f, 0.608790f,
2096       0.609510f, 0.610231f, 0.610951f, 0.611671f, 0.612392f, 0.613112f,
2097       0.613833f, 0.614553f, 0.615274f, 0.615994f, 0.616715f, 0.617435f,
2098       0.618156f, 0.618876f, 0.619597f, 0.620317f, 0.621037f, 0.621758f,
2099       0.622478f, 0.623199f, 0.623919f, 0.624640f, 0.625360f, 0.626081f,
2100       0.626801f, 0.627522f, 0.628242f, 0.628963f, 0.629683f, 0.630403f,
2101       0.631124f, 0.631844f, 0.632565f, 0.633285f, 0.634006f, 0.634726f,
2102       0.635447f, 0.636167f, 0.636888f, 0.637608f, 0.638329f, 0.639049f,
2103       0.639769f, 0.640490f, 0.641210f, 0.641931f, 0.642651f, 0.643372f,
2104       0.644092f, 0.644813f, 0.645533f, 0.646254f, 0.646974f, 0.647695f,
2105       0.648415f, 0.649135f, 0.649856f, 0.650576f, 0.651297f, 0.652017f,
2106       0.652738f, 0.653458f, 0.654179f, 0.654899f, 0.655620f, 0.656340f,
2107       0.657061f, 0.657781f, 0.658501f, 0.659222f, 0.659942f, 0.660663f,
2108       0.661383f, 0.662104f, 0.662824f, 0.663545f, 0.664265f, 0.664986f,
2109       0.665706f, 0.666427f, 0.667147f, 0.667867f, 0.668588f, 0.669308f,
2110       0.670029f, 0.670749f, 0.671470f, 0.672190f, 0.672911f, 0.673631f,
2111       0.674352f, 0.675072f, 0.675793f, 0.676513f, 0.677233f, 0.677954f,
2112       0.678674f, 0.679395f, 0.680115f, 0.680836f, 0.681556f, 0.682277f,
2113       0.682997f, 0.683718f, 0.684438f, 0.685158f, 0.685879f, 0.686599f,
2114       0.687320f, 0.688040f, 0.688761f, 0.689481f, 0.690202f, 0.690922f,
2115       0.691643f, 0.692363f, 0.693084f, 0.693804f, 0.694524f, 0.695245f,
2116       0.695965f, 0.696686f, 0.697406f, 0.698127f, 0.698847f, 0.699568f,
2117       0.700288f, 0.701009f, 0.701729f, 0.702450f, 0.703170f, 0.703891f,
2118       0.704611f, 0.705331f, 0.706052f, 0.706772f, 0.707493f, 0.708213f,
2119       0.708934f, 0.709654f, 0.710375f, 0.711095f, 0.711816f, 0.712536f,
2120       0.713256f, 0.713977f, 0.714697f, 0.715418f, 0.716138f, 0.716859f,
2121       0.717579f, 0.718300f, 0.719020f, 0.719741f, 0.720461f, 0.721182f,
2122       0.721902f, 0.722622f, 0.723343f, 0.724063f, 0.724784f, 0.725504f,
2123       0.726225f, 0.726945f, 0.727666f, 0.728386f, 0.729107f, 0.729827f,
2124       0.730548f, 0.731268f, 0.731988f, 0.732709f, 0.733429f, 0.734150f,
2125       0.734870f, 0.735591f, 0.736311f, 0.737032f, 0.737752f, 0.738473f,
2126       0.739193f, 0.739914f, 0.740634f, 0.741354f, 0.742075f, 0.742795f,
2127       0.743516f, 0.744236f, 0.744957f, 0.745677f, 0.746398f, 0.747118f,
2128       0.747839f, 0.748559f, 0.749280f, 0.750000f, 0.750720f, 0.751441f,
2129       0.752161f, 0.752882f, 0.753602f, 0.754323f, 0.755043f, 0.755764f,
2130       0.756484f, 0.757205f, 0.757925f, 0.758646f, 0.759366f, 0.760086f,
2131       0.760807f, 0.761527f, 0.762248f, 0.762968f, 0.763689f, 0.764409f,
2132       0.765130f, 0.765850f, 0.766571f, 0.767291f, 0.768012f, 0.768732f,
2133       0.769452f, 0.770173f, 0.770893f, 0.771614f, 0.772334f, 0.773055f,
2134       0.773775f, 0.774496f, 0.775216f, 0.775937f, 0.776657f, 0.777378f,
2135       0.778098f, 0.778818f, 0.779539f, 0.780259f, 0.780980f, 0.781700f,
2136       0.782421f, 0.783141f, 0.783862f, 0.784582f, 0.785303f, 0.786023f,
2137       0.786744f, 0.787464f, 0.788184f, 0.788905f, 0.789625f, 0.790346f,
2138       0.791066f, 0.791787f, 0.792507f, 0.793228f, 0.793948f, 0.794669f,
2139       0.795389f, 0.796109f, 0.796830f, 0.797550f, 0.798271f, 0.798991f,
2140       0.799712f, 0.800432f, 0.801153f, 0.801873f, 0.802594f, 0.803314f,
2141       0.804035f, 0.804755f, 0.805476f, 0.806196f, 0.806916f, 0.807637f,
2142       0.808357f, 0.809078f, 0.809798f, 0.810519f, 0.811239f, 0.811960f,
2143       0.812680f, 0.813401f, 0.814121f, 0.814842f, 0.815562f, 0.816282f,
2144       0.817003f, 0.817723f, 0.818444f, 0.819164f, 0.819885f, 0.820605f,
2145       0.821326f, 0.822046f, 0.822767f, 0.823487f, 0.824207f, 0.824928f,
2146       0.825648f, 0.826369f, 0.827089f, 0.827810f, 0.828530f, 0.829251f,
2147       0.829971f, 0.830692f, 0.831412f, 0.832133f, 0.832853f, 0.833573f,
2148       0.834294f, 0.835014f, 0.835735f, 0.836455f, 0.837176f, 0.837896f,
2149       0.838617f, 0.839337f, 0.840058f, 0.840778f, 0.841499f, 0.842219f,
2150       0.842939f, 0.843660f, 0.844380f, 0.845101f, 0.845821f, 0.846542f,
2151       0.847262f, 0.847983f, 0.848703f, 0.849424f, 0.850144f, 0.850865f,
2152       0.851585f, 0.852305f, 0.853026f, 0.853746f, 0.854467f, 0.855187f,
2153       0.855908f, 0.856628f, 0.857349f, 0.858069f, 0.858790f, 0.859510f,
2154       0.860231f, 0.860951f, 0.861671f, 0.862392f, 0.863112f, 0.863833f,
2155       0.864553f, 0.865274f, 0.865994f, 0.866715f, 0.867435f, 0.868156f,
2156       0.868876f, 0.869597f, 0.870317f, 0.871037f, 0.871758f, 0.872478f,
2157       0.873199f, 0.873919f, 0.874640f, 0.875360f, 0.876081f, 0.876801f,
2158       0.877522f, 0.878242f, 0.878963f, 0.879683f, 0.880403f, 0.881124f,
2159       0.881844f, 0.882565f, 0.883285f, 0.884006f, 0.884726f, 0.885447f,
2160       0.886167f, 0.886888f, 0.887608f, 0.888329f, 0.889049f, 0.889769f,
2161       0.890490f, 0.891210f, 0.891931f, 0.892651f, 0.893372f, 0.894092f,
2162       0.894813f, 0.895533f, 0.896254f, 0.896974f, 0.897695f, 0.898415f,
2163       0.899135f, 0.899856f, 0.900576f, 0.901297f, 0.902017f, 0.902738f,
2164       0.903458f, 0.904179f, 0.904899f, 0.905620f, 0.906340f, 0.907061f,
2165       0.907781f, 0.908501f, 0.909222f, 0.909942f, 0.910663f, 0.911383f,
2166       0.912104f, 0.912824f, 0.913545f, 0.914265f, 0.914986f, 0.915706f,
2167       0.916427f, 0.917147f, 0.917867f, 0.918588f, 0.919308f, 0.920029f,
2168       0.920749f, 0.921470f, 0.922190f, 0.922911f, 0.923631f, 0.924352f,
2169       0.925072f, 0.925793f, 0.926513f, 0.927233f, 0.927954f, 0.928674f,
2170       0.929395f, 0.930115f, 0.930836f, 0.931556f, 0.932277f, 0.932997f,
2171       0.933718f, 0.934438f, 0.935158f, 0.935879f, 0.936599f, 0.937320f,
2172       0.938040f, 0.938761f, 0.939481f, 0.940202f, 0.940922f, 0.941643f,
2173       0.942363f, 0.943084f, 0.943804f, 0.944524f, 0.945245f, 0.945965f,
2174       0.946686f, 0.947406f, 0.948127f, 0.948847f, 0.949568f, 0.950288f,
2175       0.951009f, 0.951729f, 0.952450f, 0.953170f, 0.953891f, 0.954611f,
2176       0.955331f, 0.956052f, 0.956772f, 0.957493f, 0.958213f, 0.958934f,
2177       0.959654f, 0.960375f, 0.961095f, 0.961816f, 0.962536f, 0.963256f,
2178       0.963977f, 0.964697f, 0.965418f, 0.966138f, 0.966859f, 0.967579f,
2179       0.968300f, 0.969020f, 0.969741f, 0.970461f, 0.971182f, 0.971902f,
2180       0.972622f, 0.973343f, 0.974063f, 0.974784f, 0.975504f, 0.976225f,
2181       0.976945f, 0.977666f, 0.978386f, 0.979107f, 0.979827f, 0.980548f,
2182       0.981268f, 0.981988f, 0.982709f, 0.983429f, 0.984150f, 0.984870f,
2183       0.985591f, 0.986311f, 0.987032f, 0.987752f, 0.988473f, 0.989193f,
2184       0.989914f, 0.990634f, 0.991354f, 0.992075f, 0.992795f, 0.993516f,
2185       0.994236f, 0.994957f, 0.995677f, 0.996398f, 0.997118f, 0.997839f,
2186       0.998559f, 0.999280f, 1.000000f
2187     };
2188
2189   CacheView
2190     *image_view;
2191
2192   MagickBooleanType
2193     status;
2194
2195   MagickOffsetType
2196     progress;
2197
2198   register ssize_t
2199     i;
2200
2201   ssize_t
2202     y;
2203
2204   TransformPacket
2205     *y_map,
2206     *x_map,
2207     *z_map;
2208
2209   assert(image != (Image *) NULL);
2210   assert(image->signature == MagickSignature);
2211   if (image->debug != MagickFalse)
2212     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2213   status=MagickTrue;
2214   progress=0;
2215   switch (image->colorspace)
2216   {
2217     case CMYColorspace:
2218     {
2219       /*
2220         Transform image from CMY to sRGB.
2221       */
2222       if (image->storage_class == PseudoClass)
2223         {
2224           if (SyncImage(image,exception) == MagickFalse)
2225             return(MagickFalse);
2226           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2227             return(MagickFalse);
2228         }
2229       image_view=AcquireAuthenticCacheView(image,exception);
2230 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2231       #pragma omp parallel for schedule(static,4) shared(status) \
2232         dynamic_number_threads(image,image->columns,image->rows,1)
2233 #endif
2234       for (y=0; y < (ssize_t) image->rows; y++)
2235       {
2236         MagickBooleanType
2237           sync;
2238
2239         register ssize_t
2240           x;
2241
2242         register Quantum
2243           *restrict q;
2244
2245         if (status == MagickFalse)
2246           continue;
2247         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2248           exception);
2249         if (q == (Quantum *) NULL)
2250           {
2251             status=MagickFalse;
2252             continue;
2253           }
2254         for (x=0; x < (ssize_t) image->columns; x++)
2255         {
2256           double
2257             cyan,
2258             magenta,
2259             yellow;
2260
2261           cyan=sRGBCompandor((double) (QuantumRange-
2262             GetPixelCyan(image,q)));
2263           magenta=sRGBCompandor((double) (QuantumRange-
2264             GetPixelMagenta(image,q)));
2265           yellow=sRGBCompandor((double) (QuantumRange-
2266             GetPixelYellow(image,q)));
2267           SetPixelCyan(image,ClampToQuantum(cyan),q);
2268           SetPixelMagenta(image,ClampToQuantum(magenta),q);
2269           SetPixelYellow(image,ClampToQuantum(yellow),q);
2270           q+=GetPixelChannels(image);
2271         }
2272         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2273         if (sync == MagickFalse)
2274           status=MagickFalse;
2275       }
2276       image_view=DestroyCacheView(image_view);
2277       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2278         return(MagickFalse);
2279       return(status);
2280     }
2281     case CMYKColorspace:
2282     {
2283       PixelInfo
2284         zero;
2285
2286       /*
2287         Transform image from CMYK to sRGB.
2288       */
2289       if (image->storage_class == PseudoClass)
2290         {
2291           if (SyncImage(image,exception) == MagickFalse)
2292             return(MagickFalse);
2293           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2294             return(MagickFalse);
2295         }
2296       GetPixelInfo(image,&zero);
2297       image_view=AcquireAuthenticCacheView(image,exception);
2298 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2299       #pragma omp parallel for schedule(static,4) shared(status) \
2300         dynamic_number_threads(image,image->columns,image->rows,1)
2301 #endif
2302       for (y=0; y < (ssize_t) image->rows; y++)
2303       {
2304         MagickBooleanType
2305           sync;
2306
2307         PixelInfo
2308           pixel;
2309
2310         register ssize_t
2311           x;
2312
2313         register Quantum
2314           *restrict q;
2315
2316         if (status == MagickFalse)
2317           continue;
2318         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2319           exception);
2320         if (q == (Quantum *) NULL)
2321           {
2322             status=MagickFalse;
2323             continue;
2324           }
2325         pixel=zero;
2326         for (x=0; x < (ssize_t) image->columns; x++)
2327         {
2328           GetPixelInfoPixel(image,q,&pixel);
2329           ConvertCMYKToRGB(&pixel);
2330           pixel.red=sRGBCompandor(pixel.red);
2331           pixel.green=sRGBCompandor(pixel.green);
2332           pixel.blue=sRGBCompandor(pixel.blue);
2333           SetPixelInfoPixel(image,&pixel,q);
2334           q+=GetPixelChannels(image);
2335         }
2336         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2337         if (sync == MagickFalse)
2338           status=MagickFalse;
2339       }
2340       image_view=DestroyCacheView(image_view);
2341       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2342         return(MagickFalse);
2343       return(status);
2344     }
2345     case GRAYColorspace:
2346     case Rec601LumaColorspace:
2347     case Rec709LumaColorspace:
2348     {
2349       /*
2350         Transform linear GRAY to sRGB colorspace.
2351       */
2352       if (image->storage_class == PseudoClass)
2353         {
2354           if (SyncImage(image,exception) == MagickFalse)
2355             return(MagickFalse);
2356           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2357             return(MagickFalse);
2358         }
2359       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2360         return(MagickFalse);
2361       image_view=AcquireAuthenticCacheView(image,exception);
2362 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2363       #pragma omp parallel for schedule(static,4) shared(status) \
2364         dynamic_number_threads(image,image->columns,image->rows,1)
2365 #endif
2366       for (y=0; y < (ssize_t) image->rows; y++)
2367       {
2368         MagickBooleanType
2369           sync;
2370
2371         register ssize_t
2372           x;
2373
2374         register Quantum
2375           *restrict q;
2376
2377         if (status == MagickFalse)
2378           continue;
2379         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2380           exception);
2381         if (q == (Quantum *) NULL)
2382           {
2383             status=MagickFalse;
2384             continue;
2385           }
2386         for (x=(ssize_t) image->columns; x != 0; x--)
2387         {
2388           double
2389             gray;
2390
2391           gray=sRGBCompandor((double) GetPixelGray(image,q));
2392           SetPixelRed(image,ClampToQuantum(gray),q);
2393           SetPixelGreen(image,ClampToQuantum(gray),q);
2394           SetPixelBlue(image,ClampToQuantum(gray),q);
2395           q+=GetPixelChannels(image);
2396         }
2397         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2398         if (sync == MagickFalse)
2399           status=MagickFalse;
2400       }
2401       image_view=DestroyCacheView(image_view);
2402       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2403         return(MagickFalse);
2404       return(status);
2405     }
2406     case HCLColorspace:
2407     {
2408       /*
2409         Transform image from HCL to sRGB.
2410       */
2411       if (image->storage_class == PseudoClass)
2412         {
2413           if (SyncImage(image,exception) == MagickFalse)
2414             return(MagickFalse);
2415           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2416             return(MagickFalse);
2417         }
2418       image_view=AcquireAuthenticCacheView(image,exception);
2419 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2420       #pragma omp parallel for schedule(static,4) shared(status) \
2421         dynamic_number_threads(image,image->columns,image->rows,1)
2422 #endif
2423       for (y=0; y < (ssize_t) image->rows; y++)
2424       {
2425         MagickBooleanType
2426           sync;
2427
2428         register ssize_t
2429           x;
2430
2431         register Quantum
2432           *restrict q;
2433
2434         if (status == MagickFalse)
2435           continue;
2436         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2437           exception);
2438         if (q == (Quantum *) NULL)
2439           {
2440             status=MagickFalse;
2441             continue;
2442           }
2443         for (x=0; x < (ssize_t) image->columns; x++)
2444         {
2445           double
2446             blue,
2447             chroma,
2448             green,
2449             hue,
2450             luma,
2451             red;
2452
2453           hue=(double) (QuantumScale*GetPixelRed(image,q));
2454           chroma=(double) (QuantumScale*GetPixelGreen(image,q));
2455           luma=(double) (QuantumScale*GetPixelBlue(image,q));
2456           ConvertHCLToRGB(hue,chroma,luma,&red,&green,&blue);
2457           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2458           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2459           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2460           q+=GetPixelChannels(image);
2461         }
2462         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2463         if (sync == MagickFalse)
2464           status=MagickFalse;
2465       }
2466       image_view=DestroyCacheView(image_view);
2467       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2468         return(MagickFalse);
2469       return(status);
2470     }
2471     case HSBColorspace:
2472     {
2473       /*
2474         Transform image from HSB to sRGB.
2475       */
2476       if (image->storage_class == PseudoClass)
2477         {
2478           if (SyncImage(image,exception) == MagickFalse)
2479             return(MagickFalse);
2480           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2481             return(MagickFalse);
2482         }
2483       image_view=AcquireAuthenticCacheView(image,exception);
2484 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2485       #pragma omp parallel for schedule(static,4) shared(status) \
2486         dynamic_number_threads(image,image->columns,image->rows,1)
2487 #endif
2488       for (y=0; y < (ssize_t) image->rows; y++)
2489       {
2490         MagickBooleanType
2491           sync;
2492
2493         register ssize_t
2494           x;
2495
2496         register Quantum
2497           *restrict q;
2498
2499         if (status == MagickFalse)
2500           continue;
2501         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2502           exception);
2503         if (q == (Quantum *) NULL)
2504           {
2505             status=MagickFalse;
2506             continue;
2507           }
2508         for (x=0; x < (ssize_t) image->columns; x++)
2509         {
2510           double
2511             blue,
2512             brightness,
2513             green,
2514             hue,
2515             red,
2516             saturation;
2517
2518           hue=(double) (QuantumScale*GetPixelRed(image,q));
2519           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
2520           brightness=(double) (QuantumScale*GetPixelBlue(image,q));
2521           ConvertHSBToRGB(hue,saturation,brightness,&red,&green,&blue);
2522           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2523           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2524           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2525           q+=GetPixelChannels(image);
2526         }
2527         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2528         if (sync == MagickFalse)
2529           status=MagickFalse;
2530       }
2531       image_view=DestroyCacheView(image_view);
2532       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2533         return(MagickFalse);
2534       return(status);
2535     }
2536     case HSLColorspace:
2537     {
2538       /*
2539         Transform image from HSL to sRGB.
2540       */
2541       if (image->storage_class == PseudoClass)
2542         {
2543           if (SyncImage(image,exception) == MagickFalse)
2544             return(MagickFalse);
2545           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2546             return(MagickFalse);
2547         }
2548       image_view=AcquireAuthenticCacheView(image,exception);
2549 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2550       #pragma omp parallel for schedule(static,4) shared(status) \
2551         dynamic_number_threads(image,image->columns,image->rows,1)
2552 #endif
2553       for (y=0; y < (ssize_t) image->rows; y++)
2554       {
2555         MagickBooleanType
2556           sync;
2557
2558         register ssize_t
2559           x;
2560
2561         register Quantum
2562           *restrict q;
2563
2564         if (status == MagickFalse)
2565           continue;
2566         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2567           exception);
2568         if (q == (Quantum *) NULL)
2569           {
2570             status=MagickFalse;
2571             continue;
2572           }
2573         for (x=0; x < (ssize_t) image->columns; x++)
2574         {
2575           double
2576             blue,
2577             green,
2578             hue,
2579             lightness,
2580             red,
2581             saturation;
2582
2583           hue=(double) (QuantumScale*GetPixelRed(image,q));
2584           saturation=(double) (QuantumScale*GetPixelGreen(image,q));
2585           lightness=(double) (QuantumScale*GetPixelBlue(image,q));
2586           ConvertHSLToRGB(hue,saturation,lightness,&red,&green,&blue);
2587           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2588           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2589           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2590           q+=GetPixelChannels(image);
2591         }
2592         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2593         if (sync == MagickFalse)
2594           status=MagickFalse;
2595       }
2596       image_view=DestroyCacheView(image_view);
2597       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2598         return(MagickFalse);
2599       return(status);
2600     }
2601     case HWBColorspace:
2602     {
2603       /*
2604         Transform image from HWB to sRGB.
2605       */
2606       if (image->storage_class == PseudoClass)
2607         {
2608           if (SyncImage(image,exception) == MagickFalse)
2609             return(MagickFalse);
2610           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2611             return(MagickFalse);
2612         }
2613       image_view=AcquireAuthenticCacheView(image,exception);
2614 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2615       #pragma omp parallel for schedule(static,4) shared(status) \
2616         dynamic_number_threads(image,image->columns,image->rows,1)
2617 #endif
2618       for (y=0; y < (ssize_t) image->rows; y++)
2619       {
2620         MagickBooleanType
2621           sync;
2622
2623         register ssize_t
2624           x;
2625
2626         register Quantum
2627           *restrict q;
2628
2629         if (status == MagickFalse)
2630           continue;
2631         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2632           exception);
2633         if (q == (Quantum *) NULL)
2634           {
2635             status=MagickFalse;
2636             continue;
2637           }
2638         for (x=0; x < (ssize_t) image->columns; x++)
2639         {
2640           double
2641             blackness,
2642             blue,
2643             green,
2644             hue,
2645             red,
2646             whiteness;
2647
2648           hue=(double) (QuantumScale*GetPixelRed(image,q));
2649           whiteness=(double) (QuantumScale*GetPixelGreen(image,q));
2650           blackness=(double) (QuantumScale*GetPixelBlue(image,q));
2651           ConvertHWBToRGB(hue,whiteness,blackness,&red,&green,&blue);
2652           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2653           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2654           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2655           q+=GetPixelChannels(image);
2656         }
2657         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2658         if (sync == MagickFalse)
2659           status=MagickFalse;
2660       }
2661       image_view=DestroyCacheView(image_view);
2662       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2663         return(MagickFalse);
2664       return(status);
2665     }
2666     case LabColorspace:
2667     {
2668       /*
2669         Transform image from Lab to sRGB.
2670       */
2671       if (image->storage_class == PseudoClass)
2672         {
2673           if (SyncImage(image,exception) == MagickFalse)
2674             return(MagickFalse);
2675           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2676             return(MagickFalse);
2677         }
2678       image_view=AcquireAuthenticCacheView(image,exception);
2679 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2680       #pragma omp parallel for schedule(static,4) shared(status) \
2681         dynamic_number_threads(image,image->columns,image->rows,1)
2682 #endif
2683       for (y=0; y < (ssize_t) image->rows; y++)
2684       {
2685         MagickBooleanType
2686           sync;
2687
2688         register ssize_t
2689           x;
2690
2691         register Quantum
2692           *restrict q;
2693
2694         if (status == MagickFalse)
2695           continue;
2696         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2697           exception);
2698         if (q == (Quantum *) NULL)
2699           {
2700             status=MagickFalse;
2701             continue;
2702           }
2703         for (x=0; x < (ssize_t) image->columns; x++)
2704         {
2705           double
2706             a,
2707             b,
2708             blue,
2709             green,
2710             L,
2711             red,
2712             X,
2713             Y,
2714             Z;
2715
2716           L=QuantumScale*GetPixelRed(image,q);
2717           a=QuantumScale*GetPixelGreen(image,q);
2718           b=QuantumScale*GetPixelBlue(image,q);
2719           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2720           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2721           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2722           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2723           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2724           q+=GetPixelChannels(image);
2725         }
2726         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2727         if (sync == MagickFalse)
2728           status=MagickFalse;
2729       }
2730       image_view=DestroyCacheView(image_view);
2731       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2732         return(MagickFalse);
2733       return(status);
2734     }
2735     case LCHColorspace:
2736     {
2737       /*
2738         Transform image from LCH to sRGB.
2739       */
2740       if (image->storage_class == PseudoClass)
2741         {
2742           if (SyncImage(image,exception) == MagickFalse)
2743             return(MagickFalse);
2744           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2745             return(MagickFalse);
2746         }
2747       image_view=AcquireAuthenticCacheView(image,exception);
2748 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2749       #pragma omp parallel for schedule(static,4) shared(status) \
2750         dynamic_number_threads(image,image->columns,image->rows,1)
2751 #endif
2752       for (y=0; y < (ssize_t) image->rows; y++)
2753       {
2754         MagickBooleanType
2755           sync;
2756
2757         register ssize_t
2758           x;
2759
2760         register Quantum
2761           *restrict q;
2762
2763         if (status == MagickFalse)
2764           continue;
2765         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2766           exception);
2767         if (q == (Quantum *) NULL)
2768           {
2769             status=MagickFalse;
2770             continue;
2771           }
2772         for (x=0; x < (ssize_t) image->columns; x++)
2773         {
2774           double
2775             a,
2776             b,
2777             blue,
2778             C,
2779             green,
2780             H,
2781             L,
2782             red,
2783             X,
2784             Y,
2785             Z;
2786
2787           L=QuantumScale*GetPixelRed(image,q);
2788           C=QuantumScale*GetPixelGreen(image,q);
2789           H=QuantumScale*GetPixelBlue(image,q);
2790           a=C*cos(H*(MagickPI/180.0));
2791           b=C*sin(H*(MagickPI/180.0));
2792           ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
2793           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2794           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2795           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2796           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2797           q+=GetPixelChannels(image);
2798         }
2799         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2800         if (sync == MagickFalse)
2801           status=MagickFalse;
2802       }
2803       image_view=DestroyCacheView(image_view);
2804       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2805         return(MagickFalse);
2806       return(status);
2807     }
2808     case LMSColorspace:
2809     {
2810       /*
2811         Transform image from LMS to sRGB.
2812       */
2813       if (image->storage_class == PseudoClass)
2814         {
2815           if (SyncImage(image,exception) == MagickFalse)
2816             return(MagickFalse);
2817           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2818             return(MagickFalse);
2819         }
2820       image_view=AcquireAuthenticCacheView(image,exception);
2821 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2822       #pragma omp parallel for schedule(static,4) shared(status) \
2823         dynamic_number_threads(image,image->columns,image->rows,1)
2824 #endif
2825       for (y=0; y < (ssize_t) image->rows; y++)
2826       {
2827         MagickBooleanType
2828           sync;
2829
2830         register ssize_t
2831           x;
2832
2833         register Quantum
2834           *restrict q;
2835
2836         if (status == MagickFalse)
2837           continue;
2838         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2839           exception);
2840         if (q == (Quantum *) NULL)
2841           {
2842             status=MagickFalse;
2843             continue;
2844           }
2845         for (x=0; x < (ssize_t) image->columns; x++)
2846         {
2847           double
2848             blue,
2849             green,
2850             L,
2851             M,
2852             red,
2853             S,
2854             X,
2855             Y,
2856             Z;
2857
2858           L=QuantumScale*GetPixelRed(image,q);
2859           M=QuantumScale*GetPixelGreen(image,q);
2860           S=QuantumScale*GetPixelBlue(image,q);
2861           ConvertLMSToXYZ(L,M,S,&X,&Y,&Z);
2862           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
2863           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
2864           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
2865           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
2866           q+=GetPixelChannels(image);
2867         }
2868         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2869         if (sync == MagickFalse)
2870           status=MagickFalse;
2871       }
2872       image_view=DestroyCacheView(image_view);
2873       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2874         return(MagickFalse);
2875       return(status);
2876     }
2877     case LogColorspace:
2878     {
2879       const char
2880         *value;
2881
2882       double
2883         black,
2884         density,
2885         film_gamma,
2886         gamma,
2887         reference_black,
2888         reference_white;
2889
2890       Quantum
2891         *logmap;
2892
2893       /*
2894         Transform Log to sRGB colorspace.
2895       */
2896       density=DisplayGamma;
2897       gamma=DisplayGamma;
2898       value=GetImageProperty(image,"gamma",exception);
2899       if (value != (const char *) NULL)
2900         gamma=MagickEpsilonReciprocal(StringToDouble(value,(char **) NULL));
2901       film_gamma=FilmGamma;
2902       value=GetImageProperty(image,"film-gamma",exception);
2903       if (value != (const char *) NULL)
2904         film_gamma=StringToDouble(value,(char **) NULL);
2905       reference_black=ReferenceBlack;
2906       value=GetImageProperty(image,"reference-black",exception);
2907       if (value != (const char *) NULL)
2908         reference_black=StringToDouble(value,(char **) NULL);
2909       reference_white=ReferenceWhite;
2910       value=GetImageProperty(image,"reference-white",exception);
2911       if (value != (const char *) NULL)
2912         reference_white=StringToDouble(value,(char **) NULL);
2913       logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2914         sizeof(*logmap));
2915       if (logmap == (Quantum *) NULL)
2916         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2917           image->filename);
2918       black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
2919         0.002/film_gamma);
2920       for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
2921         logmap[i]=(Quantum) 0;
2922       for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
2923         logmap[i]=ClampToQuantum(QuantumRange/(1.0-black)*
2924           (pow(10.0,(1024.0*i/MaxMap-reference_white)*
2925           (gamma/density)*0.002/film_gamma)-black));
2926       for ( ; i <= (ssize_t) MaxMap; i++)
2927         logmap[i]=QuantumRange;
2928       if (image->storage_class == PseudoClass)
2929         {
2930           if (SyncImage(image,exception) == MagickFalse)
2931             return(MagickFalse);
2932           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2933             return(MagickFalse);
2934         }
2935       image_view=AcquireAuthenticCacheView(image,exception);
2936 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2937       #pragma omp parallel for schedule(static,4) shared(status) \
2938         dynamic_number_threads(image,image->columns,image->rows,1)
2939 #endif
2940       for (y=0; y < (ssize_t) image->rows; y++)
2941       {
2942         MagickBooleanType
2943           sync;
2944
2945         register ssize_t
2946           x;
2947
2948         register Quantum
2949           *restrict q;
2950
2951         if (status == MagickFalse)
2952           continue;
2953         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2954           exception);
2955         if (q == (Quantum *) NULL)
2956           {
2957             status=MagickFalse;
2958             continue;
2959           }
2960         for (x=(ssize_t) image->columns; x != 0; x--)
2961         {
2962           double
2963             blue,
2964             green,
2965             red;
2966
2967           red=sRGBCompandor((double) logmap[ScaleQuantumToMap(
2968             GetPixelRed(image,q))]);
2969           green=sRGBCompandor((double) logmap[ScaleQuantumToMap(
2970             GetPixelGreen(image,q))]);
2971           blue=sRGBCompandor((double) logmap[ScaleQuantumToMap(
2972             GetPixelBlue(image,q))]);
2973           SetPixelRed(image,ClampToQuantum(red),q);
2974           SetPixelGreen(image,ClampToQuantum(green),q);
2975           SetPixelBlue(image,ClampToQuantum(blue),q);
2976           q+=GetPixelChannels(image);
2977         }
2978         sync=SyncCacheViewAuthenticPixels(image_view,exception);
2979         if (sync == MagickFalse)
2980           status=MagickFalse;
2981       }
2982       image_view=DestroyCacheView(image_view);
2983       logmap=(Quantum *) RelinquishMagickMemory(logmap);
2984       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
2985         return(MagickFalse);
2986       return(status);
2987     }
2988     case LuvColorspace:
2989     {
2990       /*
2991         Transform image from Luv to sRGB.
2992       */
2993       if (image->storage_class == PseudoClass)
2994         {
2995           if (SyncImage(image,exception) == MagickFalse)
2996             return(MagickFalse);
2997           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2998             return(MagickFalse);
2999         }
3000       image_view=AcquireAuthenticCacheView(image,exception);
3001 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3002       #pragma omp parallel for schedule(static,4) shared(status) \
3003         dynamic_number_threads(image,image->columns,image->rows,1)
3004 #endif
3005       for (y=0; y < (ssize_t) image->rows; y++)
3006       {
3007         MagickBooleanType
3008           sync;
3009
3010         register ssize_t
3011           x;
3012
3013         register Quantum
3014           *restrict q;
3015
3016         if (status == MagickFalse)
3017           continue;
3018         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3019           exception);
3020         if (q == (Quantum *) NULL)
3021           {
3022             status=MagickFalse;
3023             continue;
3024           }
3025         for (x=0; x < (ssize_t) image->columns; x++)
3026         {
3027           double
3028             blue,
3029             green,
3030             L,
3031             red,
3032             u,
3033             v,
3034             X,
3035             Y,
3036             Z;
3037
3038           L=QuantumScale*GetPixelRed(image,q);
3039           u=QuantumScale*GetPixelGreen(image,q);
3040           v=QuantumScale*GetPixelBlue(image,q);
3041           ConvertLuvToXYZ(L,u,v,&X,&Y,&Z);
3042           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
3043           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
3044           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
3045           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
3046           q+=GetPixelChannels(image);
3047         }
3048         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3049         if (sync == MagickFalse)
3050           status=MagickFalse;
3051       }
3052       image_view=DestroyCacheView(image_view);
3053       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3054         return(MagickFalse);
3055       return(status);
3056     }
3057     case RGBColorspace:
3058     {
3059       /*
3060         Transform linear RGB to sRGB colorspace.
3061       */
3062       if (image->storage_class == PseudoClass)
3063         {
3064           if (SyncImage(image,exception) == MagickFalse)
3065             return(MagickFalse);
3066           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3067             return(MagickFalse);
3068         }
3069       image_view=AcquireAuthenticCacheView(image,exception);
3070 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3071       #pragma omp parallel for schedule(static,4) shared(status) \
3072         dynamic_number_threads(image,image->columns,image->rows,1)
3073 #endif
3074       for (y=0; y < (ssize_t) image->rows; y++)
3075       {
3076         MagickBooleanType
3077           sync;
3078
3079         register ssize_t
3080           x;
3081
3082         register Quantum
3083           *restrict q;
3084
3085         if (status == MagickFalse)
3086           continue;
3087         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3088           exception);
3089         if (q == (Quantum *) NULL)
3090           {
3091             status=MagickFalse;
3092             continue;
3093           }
3094         for (x=(ssize_t) image->columns; x != 0; x--)
3095         {
3096           double
3097             blue,
3098             green,
3099             red;
3100
3101           red=sRGBCompandor((double) GetPixelRed(image,q));
3102           green=sRGBCompandor((double) GetPixelGreen(image,q));
3103           blue=sRGBCompandor((double) GetPixelBlue(image,q));
3104           SetPixelRed(image,ClampToQuantum(red),q);
3105           SetPixelGreen(image,ClampToQuantum(green),q);
3106           SetPixelBlue(image,ClampToQuantum(blue),q);
3107           q+=GetPixelChannels(image);
3108         }
3109         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3110         if (sync == MagickFalse)
3111           status=MagickFalse;
3112       }
3113       image_view=DestroyCacheView(image_view);
3114       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3115         return(MagickFalse);
3116       return(status);
3117     }
3118     case XYZColorspace:
3119     {
3120       /*
3121         Transform image from XYZ to sRGB.
3122       */
3123       if (image->storage_class == PseudoClass)
3124         {
3125           if (SyncImage(image,exception) == MagickFalse)
3126             return(MagickFalse);
3127           if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
3128             return(MagickFalse);
3129         }
3130       image_view=AcquireAuthenticCacheView(image,exception);
3131 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3132       #pragma omp parallel for schedule(static,4) shared(status) \
3133         dynamic_number_threads(image,image->columns,image->rows,1)
3134 #endif
3135       for (y=0; y < (ssize_t) image->rows; y++)
3136       {
3137         MagickBooleanType
3138           sync;
3139
3140         register ssize_t
3141           x;
3142
3143         register Quantum
3144           *restrict q;
3145
3146         if (status == MagickFalse)
3147           continue;
3148         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3149           exception);
3150         if (q == (Quantum *) NULL)
3151           {
3152             status=MagickFalse;
3153             continue;
3154           }
3155         for (x=0; x < (ssize_t) image->columns; x++)
3156         {
3157           double
3158             blue,
3159             green,
3160             red,
3161             X,
3162             Y,
3163             Z;
3164
3165           X=QuantumScale*GetPixelRed(image,q);
3166           Y=QuantumScale*GetPixelGreen(image,q);
3167           Z=QuantumScale*GetPixelBlue(image,q);
3168           ConvertXYZToRGB(X,Y,Z,&red,&green,&blue);
3169           SetPixelRed(image,ClampToQuantum(sRGBCompandor(red)),q);
3170           SetPixelGreen(image,ClampToQuantum(sRGBCompandor(green)),q);
3171           SetPixelBlue(image,ClampToQuantum(sRGBCompandor(blue)),q);
3172           q+=GetPixelChannels(image);
3173         }
3174         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3175         if (sync == MagickFalse)
3176           status=MagickFalse;
3177       }
3178       image_view=DestroyCacheView(image_view);
3179       if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3180         return(MagickFalse);
3181       return(status);
3182     }
3183     default:
3184       break;
3185   }
3186   /*
3187     Allocate the tables.
3188   */
3189   x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3190     sizeof(*x_map));
3191   y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3192     sizeof(*y_map));
3193   z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
3194     sizeof(*z_map));
3195   if ((x_map == (TransformPacket *) NULL) ||
3196       (y_map == (TransformPacket *) NULL) ||
3197       (z_map == (TransformPacket *) NULL))
3198     {
3199       if (z_map != (TransformPacket *) NULL)
3200         z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
3201       if (y_map != (TransformPacket *) NULL)
3202         y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
3203       if (x_map != (TransformPacket *) NULL)
3204         x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
3205       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
3206         image->filename);
3207     }
3208   switch (image->colorspace)
3209   {
3210     case OHTAColorspace:
3211     {
3212       /*
3213         Initialize OHTA tables:
3214
3215           R = I1+1.00000*I2-0.66668*I3
3216           G = I1+0.00000*I2+1.33333*I3
3217           B = I1-1.00000*I2-0.66668*I3
3218
3219         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
3220         through QuantumRange.
3221       */
3222 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3223       #pragma omp parallel for schedule(static,4) \
3224         dynamic_number_threads(image,image->columns,1,1)
3225 #endif
3226       for (i=0; i <= (ssize_t) MaxMap; i++)
3227       {
3228         x_map[i].x=1.0*i;
3229         y_map[i].x=0.5*(2.0*i-MaxMap);
3230         z_map[i].x=(-0.333340)*(2.0*i-MaxMap);
3231         x_map[i].y=1.0*i;
3232         y_map[i].y=0.000000;
3233         z_map[i].y=0.666665*(2.0*i-MaxMap);
3234         x_map[i].z=1.0*i;
3235         y_map[i].z=(-0.500000)*(2.0*i-MaxMap);
3236         z_map[i].z=(-0.333340)*(2.0*i-MaxMap);
3237       }
3238       break;
3239     }
3240     case Rec601YCbCrColorspace:
3241     case YCbCrColorspace:
3242     {
3243       /*
3244         Initialize YCbCr tables:
3245
3246           R = Y            +1.402000*Cr
3247           G = Y-0.344136*Cb-0.714136*Cr
3248           B = Y+1.772000*Cb
3249
3250         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
3251         through QuantumRange.
3252       */
3253 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3254       #pragma omp parallel for schedule(static,4) \
3255         dynamic_number_threads(image,image->columns,1,1)
3256 #endif
3257       for (i=0; i <= (ssize_t) MaxMap; i++)
3258       {
3259         x_map[i].x=0.99999999999914679361*i;
3260         y_map[i].x=(1.2188941887145875e-06)*i;
3261         z_map[i].x=0.5*1.4019995886561440468*(2.00*i-MaxMap);
3262         x_map[i].y=0.99999975910502514331*i;
3263         y_map[i].y=0.5*(-0.34413567816504303521)*(2.00*i-MaxMap);
3264         z_map[i].y=0.5*(-0.71413649331646789076)*(2.00*i-MaxMap);
3265         x_map[i].z=1.00000124040004623180*i;
3266         y_map[i].z=0.5*1.77200006607230409200*(2.00*i-MaxMap);
3267         z_map[i].z=2.1453384174593273e-06*i;
3268       }
3269       break;
3270     }
3271     case Rec709YCbCrColorspace:
3272     {
3273       /*
3274         Initialize YCbCr tables:
3275
3276           R = Y            +1.574800*Cr
3277           G = Y-0.187324*Cb-0.468124*Cr
3278           B = Y+1.855600*Cb
3279
3280         Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
3281         through QuantumRange.
3282       */
3283 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3284       #pragma omp parallel for schedule(static,4) \
3285         dynamic_number_threads(image,image->columns,1,1)
3286 #endif
3287       for (i=0; i <= (ssize_t) MaxMap; i++)
3288       {
3289         x_map[i].x=1.0*i;
3290         y_map[i].x=0.000000*(2.0*i-MaxMap);
3291         z_map[i].x=0.5*1.574800*(2.0*i-MaxMap);
3292         x_map[i].y=1.0*i;
3293         y_map[i].y=0.5*(-0.187324)*(2.0*i-MaxMap);
3294         z_map[i].y=0.5*(-0.468124)*(2.0*i-MaxMap);
3295         x_map[i].z=1.0*i;
3296         y_map[i].z=0.5*1.855600*(2.0*i-MaxMap);
3297         z_map[i].z=0.000000*(2.0*i-MaxMap);
3298       }
3299       break;
3300     }
3301     case YCCColorspace:
3302     {
3303       /*
3304         Initialize YCC tables:
3305
3306           R = Y            +1.340762*C2
3307           G = Y-0.317038*C1-0.682243*C2
3308           B = Y+1.632639*C1
3309
3310         YCC is scaled by 1.3584.  C1 zero is 156 and C2 is at 137.
3311       */
3312 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3313       #pragma omp parallel for schedule(static,4) \
3314         dynamic_number_threads(image,image->columns,1,1)
3315 #endif
3316       for (i=0; i <= (ssize_t) MaxMap; i++)
3317       {
3318         x_map[i].x=1.3584000*i;
3319         y_map[i].x=0.0000000;
3320         z_map[i].x=1.8215000*(1.0*i-(double)
3321           ScaleQuantumToMap(ScaleCharToQuantum(137)));
3322         x_map[i].y=1.3584000*i;
3323         y_map[i].y=(-0.4302726)*(1.0*i-(double)
3324           ScaleQuantumToMap(ScaleCharToQuantum(156)));
3325         z_map[i].y=(-0.9271435)*(1.0*i-(double)
3326           ScaleQuantumToMap(ScaleCharToQuantum(137)));
3327         x_map[i].z=1.3584000*i;
3328         y_map[i].z=2.2179000*(1.0*i-(double)
3329           ScaleQuantumToMap(ScaleCharToQuantum(156)));
3330         z_map[i].z=0.0000000;
3331       }
3332       break;
3333     }
3334     case YIQColorspace:
3335     {
3336       /*
3337         Initialize YIQ tables:
3338
3339           R = Y+0.95620*I+0.62140*Q
3340           G = Y-0.27270*I-0.64680*Q
3341           B = Y-1.10370*I+1.70060*Q
3342
3343         I and Q, normally -0.5 through 0.5, must be normalized to the range 0
3344         through QuantumRange.
3345       */
3346 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3347       #pragma omp parallel for schedule(static,4) \
3348         dynamic_number_threads(image,image->columns,1,1)
3349 #endif
3350       for (i=0; i <= (ssize_t) MaxMap; i++)
3351       {
3352         x_map[i].x=1.0*i;
3353         y_map[i].x=0.5*0.9562957197589482261*(2.00000*i-MaxMap);
3354         z_map[i].x=0.5*0.6210244164652610754*(2.00000*i-MaxMap);
3355         x_map[i].y=1.0*i;
3356         y_map[i].y=0.5*(-0.2721220993185104464)*(2.00000*i-MaxMap);
3357         z_map[i].y=0.5*(-0.6473805968256950427)*(2.00000*i-MaxMap);
3358         x_map[i].z=1.0*i;
3359         y_map[i].z=0.5*(-1.1069890167364901945)*(2.00000*i-MaxMap);
3360         z_map[i].z=0.5*1.7046149983646481374*(2.00000*i-MaxMap);
3361       }
3362       break;
3363     }
3364     case YPbPrColorspace:
3365     {
3366       /*
3367         Initialize YPbPr tables:
3368
3369           R = Y            +1.402000*C2
3370           G = Y-0.344136*C1+0.714136*C2
3371           B = Y+1.772000*C1
3372
3373         Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
3374         through QuantumRange.
3375       */
3376 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3377       #pragma omp parallel for schedule(static,4) \
3378         dynamic_number_threads(image,image->columns,1,1)
3379 #endif
3380       for (i=0; i <= (ssize_t) MaxMap; i++)
3381       {
3382         x_map[i].x=0.99999999999914679361*i;
3383         y_map[i].x=(-1.2188941887145875e-06)*(2.0*i-MaxMap);
3384         z_map[i].x=0.5*1.4019995886561440468*(2.0*i-MaxMap);
3385         x_map[i].y=0.99999975910502514331*i;
3386         y_map[i].y=0.5*(-0.34413567816504303521)*(2.0*i-MaxMap);
3387         z_map[i].y=0.5*(-0.71413649331646789076)*(2.0*i-MaxMap);
3388         x_map[i].z=1.00000124040004623180*i;
3389         y_map[i].z=0.5*1.77200006607230409200*(2.0*i-MaxMap);
3390         z_map[i].z=2.1453384174593273e-06*(2.0*i-MaxMap);
3391       }
3392       break;
3393     }
3394     case YUVColorspace:
3395     {
3396       /*
3397         Initialize YUV tables:
3398
3399           R = Y         +1.13983*V
3400           G = Y-0.39464*U-0.58060*V
3401           B = Y+2.03211*U
3402
3403         U and V, normally -0.5 through 0.5, must be normalized to the range 0
3404         through QuantumRange.
3405       */
3406 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3407       #pragma omp parallel for schedule(static,4) \
3408         dynamic_number_threads(image,image->columns,1,1)
3409 #endif
3410       for (i=0; i <= (ssize_t) MaxMap; i++)
3411       {
3412         x_map[i].x=1.0*i;
3413         y_map[i].x=(-3.945707070708279e-05)*(2.0*i-MaxMap);
3414         z_map[i].x=0.5*1.1398279671717170825*(2.0*i-MaxMap);
3415         x_map[i].y=1.0*i;
3416         y_map[i].y=0.5*(-0.3946101641414141437)*(2.0*i-MaxMap);
3417         z_map[i].y=0.5*(-0.5805003156565656797)*(2.0*i-MaxMap);
3418         x_map[i].z=1.0*i;
3419         y_map[i].z=0.5*2.0319996843434342537*(2.0*i-MaxMap);
3420         z_map[i].z=(-4.813762626262513e-04)*(2.0*i-MaxMap);
3421       }
3422       break;
3423     }
3424     default:
3425     {
3426       /*
3427         Linear conversion tables.
3428       */
3429 #if defined(MAGICKCORE_OPENMP_SUPPORT) && !defined(NoBenefitFromParallelism)
3430       #pragma omp parallel for schedule(static,4) \
3431         dynamic_number_threads(image,image->columns,1,1)
3432 #endif
3433       for (i=0; i <= (ssize_t) MaxMap; i++)
3434       {
3435         x_map[i].x=1.0*i;
3436         y_map[i].x=0.0;
3437         z_map[i].x=0.0;
3438         x_map[i].y=0.0;
3439         y_map[i].y=1.0*i;
3440         z_map[i].y=0.0;
3441         x_map[i].z=0.0;
3442         y_map[i].z=0.0;
3443         z_map[i].z=1.0*i;
3444       }
3445       break;
3446     }
3447   }
3448   /*
3449     Convert to sRGB.
3450   */
3451   switch (image->storage_class)
3452   {
3453     case DirectClass:
3454     default:
3455     {
3456       /*
3457         Convert DirectClass image.
3458       */
3459       image_view=AcquireAuthenticCacheView(image,exception);
3460 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3461       #pragma omp parallel for schedule(static,4) shared(status) \
3462         dynamic_number_threads(image,image->columns,image->rows,1)
3463 #endif
3464       for (y=0; y < (ssize_t) image->rows; y++)
3465       {
3466         MagickBooleanType
3467           sync;
3468
3469         PixelInfo
3470           pixel;
3471
3472         register ssize_t
3473           x;
3474
3475         register Quantum
3476           *restrict q;
3477
3478         if (status == MagickFalse)
3479           continue;
3480         q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
3481           exception);
3482         if (q == (Quantum *) NULL)
3483           {
3484             status=MagickFalse;
3485             continue;
3486           }
3487         for (x=0; x < (ssize_t) image->columns; x++)
3488         {
3489           register size_t
3490             blue,
3491             green,
3492             red;
3493
3494           red=ScaleQuantumToMap(GetPixelRed(image,q));
3495           green=ScaleQuantumToMap(GetPixelGreen(image,q));
3496           blue=ScaleQuantumToMap(GetPixelBlue(image,q));
3497           pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
3498           pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
3499           pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
3500           if (image->colorspace == YCCColorspace)
3501             {
3502               pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3503                 pixel.red)];
3504               pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3505                 pixel.green)];
3506               pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3507                 pixel.blue)];
3508             }
3509           else
3510             {
3511               pixel.red=sRGBCompandor(pixel.red);
3512               pixel.green=sRGBCompandor(pixel.green);
3513               pixel.blue=sRGBCompandor(pixel.blue);
3514             }
3515           SetPixelRed(image,ClampToQuantum((double)
3516             ScaleMapToQuantum(pixel.red)),q);
3517           SetPixelGreen(image,ClampToQuantum((double)
3518             ScaleMapToQuantum(pixel.green)),q);
3519           SetPixelBlue(image,ClampToQuantum((double)
3520             ScaleMapToQuantum(pixel.blue)),q);
3521           q+=GetPixelChannels(image);
3522         }
3523         sync=SyncCacheViewAuthenticPixels(image_view,exception);
3524         if (sync == MagickFalse)
3525           status=MagickFalse;
3526         if (image->progress_monitor != (MagickProgressMonitor) NULL)
3527           {
3528             MagickBooleanType
3529               proceed;
3530
3531 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3532             #pragma omp critical (MagickCore_TransformsRGBImage)
3533 #endif
3534             proceed=SetImageProgress(image,TransformsRGBImageTag,progress++,
3535               image->rows);
3536             if (proceed == MagickFalse)
3537               status=MagickFalse;
3538           }
3539       }
3540       image_view=DestroyCacheView(image_view);
3541       break;
3542     }
3543     case PseudoClass:
3544     {
3545       /*
3546         Convert PseudoClass image.
3547       */
3548 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3549       #pragma omp parallel for schedule(static,4) shared(status) \
3550         dynamic_number_threads(image,image->columns,1,1)
3551 #endif
3552       for (i=0; i < (ssize_t) image->colors; i++)
3553       {
3554         PixelInfo
3555           pixel;
3556
3557         register size_t
3558           blue,
3559           green,
3560           red;
3561
3562         red=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].red));
3563         green=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].green));
3564         blue=ScaleQuantumToMap(ClampToQuantum(image->colormap[i].blue));
3565         pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
3566         pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
3567         pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
3568         if (image->colorspace == YCCColorspace)
3569           {
3570             pixel.red=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3571               pixel.red)];
3572             pixel.green=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3573               pixel.green)];
3574             pixel.blue=QuantumRange*YCCMap[RoundToYCC(1024.0*QuantumScale*
3575               pixel.blue)];
3576           }
3577         else
3578           {
3579             pixel.red=sRGBCompandor(pixel.red);
3580             pixel.green=sRGBCompandor(pixel.green);
3581             pixel.blue=sRGBCompandor(pixel.blue);
3582           }
3583         image->colormap[i].red=(double) ClampToQuantum((double)
3584           ScaleMapToQuantum(pixel.red));
3585         image->colormap[i].green=(double) ClampToQuantum((double)
3586           ScaleMapToQuantum(pixel.green));
3587         image->colormap[i].blue=(double) ClampToQuantum((double)
3588           ScaleMapToQuantum(pixel.blue));
3589       }
3590       (void) SyncImage(image,exception);
3591       break;
3592     }
3593   }
3594   /*
3595     Relinquish resources.
3596   */
3597   z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
3598   y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
3599   x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
3600   if (SetImageColorspace(image,sRGBColorspace,exception) == MagickFalse)
3601     return(MagickFalse);
3602   return(MagickTrue);
3603 }