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