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