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