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