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