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