source: ImageMagick/trunk/MagickCore/colorspace.c @ 7503

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