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