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