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