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