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