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