MagickCore 6.9.13
Loading...
Searching...
No Matches
colorspace.c
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% CCCC OOO L OOO RRRR SSSSS PPPP AAA CCCC EEEEE %
7% C O O L O O R R SS P P A A C E %
8% C O O L O O RRRR SSS PPPP AAAAA C EEE %
9% C O O L O O R R SS P A A C E %
10% CCCC OOO LLLLL OOO R R SSSSS P A A CCCC EEEEE %
11% %
12% %
13% MagickCore Image Colorspace Methods %
14% %
15% Software Design %
16% Cristy %
17% July 1992 %
18% %
19% %
20% Copyright 1999 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% https://imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "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 return(MagickFalse);
2451 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2452 return(MagickFalse);
2453 }
2454 image_view=AcquireAuthenticCacheView(image,exception);
2455#if defined(MAGICKCORE_OPENMP_SUPPORT)
2456 #pragma omp parallel for schedule(static) shared(status) \
2457 magick_number_threads(image,image,image->rows,2)
2458#endif
2459 for (y=0; y < (ssize_t) image->rows; y++)
2460 {
2461 MagickBooleanType
2462 sync;
2463
2464 ssize_t
2465 x;
2466
2467 PixelPacket
2468 *magick_restrict q;
2469
2470 if (status == MagickFalse)
2471 continue;
2472 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2473 exception);
2474 if (q == (PixelPacket *) NULL)
2475 {
2476 status=MagickFalse;
2477 continue;
2478 }
2479 for (x=(ssize_t) image->columns; x != 0; x--)
2480 {
2481 Quantum
2482 blue,
2483 green,
2484 red;
2485
2486 red=ClampToQuantum(EncodePixelGamma((MagickRealType)
2487 logmap[ScaleQuantumToMap(GetPixelRed(q))]));
2488 green=ClampToQuantum(EncodePixelGamma((MagickRealType)
2489 logmap[ScaleQuantumToMap(GetPixelGreen(q))]));
2490 blue=ClampToQuantum(EncodePixelGamma((MagickRealType)
2491 logmap[ScaleQuantumToMap(GetPixelBlue(q))]));
2492 SetPixelRed(q,red);
2493 SetPixelGreen(q,green);
2494 SetPixelBlue(q,blue);
2495 q++;
2496 }
2497 sync=SyncCacheViewAuthenticPixels(image_view,exception);
2498 if (sync == MagickFalse)
2499 status=MagickFalse;
2500 }
2501 image_view=DestroyCacheView(image_view);
2502 logmap=(Quantum *) RelinquishMagickMemory(logmap);
2503 if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2504 return(MagickFalse);
2505 return(status);
2506 }
2507 case RGBColorspace:
2508 case scRGBColorspace:
2509 {
2510 /*
2511 Transform linear RGB to sRGB colorspace.
2512 */
2513 if (image->storage_class == PseudoClass)
2514 {
2515 if (SyncImage(image) == MagickFalse)
2516 return(MagickFalse);
2517 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2518 return(MagickFalse);
2519 }
2520 image_view=AcquireAuthenticCacheView(image,exception);
2521#if defined(MAGICKCORE_OPENMP_SUPPORT)
2522 #pragma omp parallel for schedule(static) shared(status) \
2523 magick_number_threads(image,image,image->rows,2)
2524#endif
2525 for (y=0; y < (ssize_t) image->rows; y++)
2526 {
2527 MagickBooleanType
2528 sync;
2529
2530 ssize_t
2531 x;
2532
2533 PixelPacket
2534 *magick_restrict q;
2535
2536 if (status == MagickFalse)
2537 continue;
2538 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2539 exception);
2540 if (q == (PixelPacket *) NULL)
2541 {
2542 status=MagickFalse;
2543 continue;
2544 }
2545 for (x=(ssize_t) image->columns; x != 0; x--)
2546 {
2547 Quantum
2548 blue,
2549 green,
2550 red;
2551
2552 red=ClampToQuantum(EncodePixelGamma((MagickRealType) GetPixelRed(q)));
2553 green=ClampToQuantum(EncodePixelGamma((MagickRealType)
2554 GetPixelGreen(q)));
2555 blue=ClampToQuantum(EncodePixelGamma((MagickRealType)
2556 GetPixelBlue(q)));
2557 SetPixelRed(q,red);
2558 SetPixelGreen(q,green);
2559 SetPixelBlue(q,blue);
2560 q++;
2561 }
2562 sync=SyncCacheViewAuthenticPixels(image_view,exception);
2563 if (sync == MagickFalse)
2564 status=MagickFalse;
2565 }
2566 image_view=DestroyCacheView(image_view);
2567 if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2568 return(MagickFalse);
2569 return(status);
2570 }
2571 default:
2572 break;
2573 }
2574 /*
2575 Allocate the tables.
2576 */
2577 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2578 sizeof(*x_map));
2579 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2580 sizeof(*y_map));
2581 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
2582 sizeof(*z_map));
2583 if ((x_map == (TransformPacket *) NULL) ||
2584 (y_map == (TransformPacket *) NULL) ||
2585 (z_map == (TransformPacket *) NULL))
2586 {
2587 if (z_map != (TransformPacket *) NULL)
2588 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2589 if (y_map != (TransformPacket *) NULL)
2590 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2591 if (x_map != (TransformPacket *) NULL)
2592 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2593 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
2594 image->filename);
2595 }
2596 switch (colorspace)
2597 {
2598 case OHTAColorspace:
2599 {
2600 /*
2601 Initialize OHTA tables:
2602
2603 R = I1+1.00000*I2-0.66668*I3
2604 G = I1+0.00000*I2+1.33333*I3
2605 B = I1-1.00000*I2-0.66668*I3
2606
2607 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2608 through QuantumRange.
2609 */
2610#if defined(MAGICKCORE_OPENMP_SUPPORT)
2611 #pragma omp parallel for schedule(static)
2612#endif
2613 for (i=0; i <= (ssize_t) MaxMap; i++)
2614 {
2615 x_map[i].x=(1.0*(double) i);
2616 y_map[i].x=(0.5*1.00000*(2.0*(double) i-MaxMap));
2617 z_map[i].x=(-0.5*0.66668*(2.0*(double) i-MaxMap));
2618 x_map[i].y=(1.0*(double) i);
2619 y_map[i].y=(0.5*0.00000*(2.0*(double) i-MaxMap));
2620 z_map[i].y=(0.5*1.33333*(2.0*(double) i-MaxMap));
2621 x_map[i].z=(1.0*(double) i);
2622 y_map[i].z=(-0.5*1.00000*(2.0*(double) i-MaxMap));
2623 z_map[i].z=(-0.5*0.66668*(2.0*(double) i-MaxMap));
2624 }
2625 break;
2626 }
2627 case Rec601YCbCrColorspace:
2628 {
2629 /*
2630 Initialize YCbCr tables:
2631
2632 R = Y +1.402000*Cr
2633 G = Y-0.344136*Cb-0.714136*Cr
2634 B = Y+1.772000*Cb
2635
2636 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2637 through QuantumRange.
2638 */
2639#if defined(MAGICKCORE_OPENMP_SUPPORT)
2640 #pragma omp parallel for schedule(static)
2641#endif
2642 for (i=0; i <= (ssize_t) MaxMap; i++)
2643 {
2644 x_map[i].x=0.99999999999914679361*(double) i;
2645 y_map[i].x=0.5*(-1.2188941887145875e-06)*(2.00*(double) i-MaxMap);
2646 z_map[i].x=0.5*1.4019995886561440468*(2.00*(double) i-MaxMap);
2647 x_map[i].y=0.99999975910502514331*(double) i;
2648 y_map[i].y=0.5*(-0.34413567816504303521)*(2.00*(double) i-MaxMap);
2649 z_map[i].y=0.5*(-0.71413649331646789076)*(2.00*(double) i-MaxMap);
2650 x_map[i].z=1.00000124040004623180*(double) i;
2651 y_map[i].z=0.5*1.77200006607230409200*(2.00*(double) i-MaxMap);
2652 z_map[i].z=0.5*2.1453384174593273e-06*(2.00*(double) i-MaxMap);
2653 }
2654 break;
2655 }
2656 case Rec709YCbCrColorspace:
2657 {
2658 /*
2659 Initialize YCbCr tables:
2660
2661 R = Y +1.574800*Cr
2662 G = Y-0.187324*Cb-0.468124*Cr
2663 B = Y+1.855600*Cb
2664
2665 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
2666 through QuantumRange.
2667 */
2668#if defined(MAGICKCORE_OPENMP_SUPPORT)
2669 #pragma omp parallel for schedule(static)
2670#endif
2671 for (i=0; i <= (ssize_t) MaxMap; i++)
2672 {
2673 x_map[i].x=(MagickRealType) (1.0*(double) i);
2674 y_map[i].x=(MagickRealType) (0.5*0.000000*(2.0*(double) i-MaxMap));
2675 z_map[i].x=(MagickRealType) (0.5*1.574800*(2.0*(double) i-MaxMap));
2676 x_map[i].y=(MagickRealType) (1.0*(double) i);
2677 y_map[i].y=(MagickRealType) (0.5*(-0.187324)*(2.0*(double) i-MaxMap));
2678 z_map[i].y=(MagickRealType) (0.5*(-0.468124)*(2.0*(double) i-MaxMap));
2679 x_map[i].z=(MagickRealType) (1.0*(double) i);
2680 y_map[i].z=(MagickRealType) (0.5*1.855600*(2.0*(double) i-MaxMap));
2681 z_map[i].z=(MagickRealType) (0.5*0.000000*(2.0*(double) i-MaxMap));
2682 }
2683 break;
2684 }
2685 case YCCColorspace:
2686 {
2687 /*
2688 Initialize YCC tables:
2689
2690 R = Y +1.340762*C2
2691 G = Y-0.317038*C1-0.682243*C2
2692 B = Y+1.632639*C1
2693
2694 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
2695 */
2696#if defined(MAGICKCORE_OPENMP_SUPPORT)
2697 #pragma omp parallel for schedule(static)
2698#endif
2699 for (i=0; i <= (ssize_t) MaxMap; i++)
2700 {
2701 x_map[i].x=(MagickRealType) (1.3584000*(double) i);
2702 y_map[i].x=(MagickRealType) (0.0000000);
2703 z_map[i].x=(MagickRealType) (1.8215000*((double) i-(MagickRealType)
2704 ScaleQuantumToMap(ScaleCharToQuantum(137))));
2705 x_map[i].y=(MagickRealType) (1.3584000*(double) i);
2706 y_map[i].y=(MagickRealType) ((-0.4302726)*((double) i-(MagickRealType)
2707 ScaleQuantumToMap(ScaleCharToQuantum(156))));
2708 z_map[i].y=(MagickRealType) ((-0.9271435)*((double) i-(MagickRealType)
2709 ScaleQuantumToMap(ScaleCharToQuantum(137))));
2710 x_map[i].z=(MagickRealType) (1.3584000*(double) i);
2711 y_map[i].z=(MagickRealType) (2.2179000*((double) i-(MagickRealType)
2712 ScaleQuantumToMap(ScaleCharToQuantum(156))));
2713 z_map[i].z=(MagickRealType) (0.0000000);
2714 }
2715 break;
2716 }
2717 default:
2718 {
2719 /*
2720 Linear conversion tables.
2721 */
2722#if defined(MAGICKCORE_OPENMP_SUPPORT)
2723 #pragma omp parallel for schedule(static)
2724#endif
2725 for (i=0; i <= (ssize_t) MaxMap; i++)
2726 {
2727 x_map[i].x=(MagickRealType) (1.0*(double) i);
2728 y_map[i].x=(MagickRealType) 0.0;
2729 z_map[i].x=(MagickRealType) 0.0;
2730 x_map[i].y=(MagickRealType) 0.0;
2731 y_map[i].y=(MagickRealType) (1.0*(double) i);
2732 z_map[i].y=(MagickRealType) 0.0;
2733 x_map[i].z=(MagickRealType) 0.0;
2734 y_map[i].z=(MagickRealType) 0.0;
2735 z_map[i].z=(MagickRealType) (1.0*(double) i);
2736 }
2737 break;
2738 }
2739 }
2740 /*
2741 Convert to sRGB.
2742 */
2743 switch (image->storage_class)
2744 {
2745 case DirectClass:
2746 default:
2747 {
2748 /*
2749 Convert DirectClass image.
2750 */
2751 image_view=AcquireAuthenticCacheView(image,exception);
2752#if defined(MAGICKCORE_OPENMP_SUPPORT)
2753 #pragma omp parallel for schedule(static) shared(status) \
2754 magick_number_threads(image,image,image->rows,2)
2755#endif
2756 for (y=0; y < (ssize_t) image->rows; y++)
2757 {
2758 MagickBooleanType
2759 sync;
2760
2761 MagickPixelPacket
2762 pixel;
2763
2764 ssize_t
2765 x;
2766
2767 PixelPacket
2768 *magick_restrict q;
2769
2770 if (status == MagickFalse)
2771 continue;
2772 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2773 exception);
2774 if (q == (PixelPacket *) NULL)
2775 {
2776 status=MagickFalse;
2777 continue;
2778 }
2779 for (x=0; x < (ssize_t) image->columns; x++)
2780 {
2781 size_t
2782 blue,
2783 green,
2784 red;
2785
2786 red=ScaleQuantumToMap(GetPixelRed(q));
2787 green=ScaleQuantumToMap(GetPixelGreen(q));
2788 blue=ScaleQuantumToMap(GetPixelBlue(q));
2789 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2790 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2791 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2792 if (colorspace == YCCColorspace)
2793 {
2794 pixel.red=QuantumRange*YCCMap[RoundToYCC(
2795 MaximumLogarithmicColorspace*pixel.red/(double) MaxMap)];
2796 pixel.green=QuantumRange*YCCMap[RoundToYCC(
2797 MaximumLogarithmicColorspace*pixel.green/(double) MaxMap)];
2798 pixel.blue=QuantumRange*YCCMap[RoundToYCC(
2799 MaximumLogarithmicColorspace*pixel.blue/(double) MaxMap)];
2800 }
2801 else
2802 {
2803 pixel.red=(MagickRealType) ScaleMapToQuantum(pixel.red);
2804 pixel.green=(MagickRealType) ScaleMapToQuantum(pixel.green);
2805 pixel.blue=(MagickRealType) ScaleMapToQuantum(pixel.blue);
2806 }
2807 SetPixelRed(q,ClampToQuantum(pixel.red));
2808 SetPixelGreen(q,ClampToQuantum(pixel.green));
2809 SetPixelBlue(q,ClampToQuantum(pixel.blue));
2810 q++;
2811 }
2812 sync=SyncCacheViewAuthenticPixels(image_view,exception);
2813 if (sync == MagickFalse)
2814 status=MagickFalse;
2815 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2816 {
2817 MagickBooleanType
2818 proceed;
2819
2820#if defined(MAGICKCORE_OPENMP_SUPPORT)
2821 #pragma omp atomic
2822#endif
2823 progress++;
2824 proceed=SetImageProgress(image,TransformRGBImageTag,progress,
2825 image->rows);
2826 if (proceed == MagickFalse)
2827 status=MagickFalse;
2828 }
2829 }
2830 image_view=DestroyCacheView(image_view);
2831 break;
2832 }
2833 case PseudoClass:
2834 {
2835 /*
2836 Convert PseudoClass image.
2837 */
2838#if defined(MAGICKCORE_OPENMP_SUPPORT)
2839 #pragma omp parallel for schedule(static) shared(status) \
2840 magick_number_threads(image,image,image->colors,1)
2841#endif
2842 for (i=0; i < (ssize_t) image->colors; i++)
2843 {
2844 MagickPixelPacket
2845 pixel;
2846
2847 size_t
2848 blue,
2849 green,
2850 red;
2851
2852 red=ScaleQuantumToMap(image->colormap[i].red);
2853 green=ScaleQuantumToMap(image->colormap[i].green);
2854 blue=ScaleQuantumToMap(image->colormap[i].blue);
2855 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2856 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2857 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2858 if (colorspace == YCCColorspace)
2859 {
2860 pixel.red=QuantumRange*YCCMap[RoundToYCC(
2861 MaximumLogarithmicColorspace*pixel.red/(double) MaxMap)];
2862 pixel.green=QuantumRange*YCCMap[RoundToYCC(
2863 MaximumLogarithmicColorspace*pixel.green/(double) MaxMap)];
2864 pixel.blue=QuantumRange*YCCMap[RoundToYCC(
2865 MaximumLogarithmicColorspace*pixel.blue/(double) MaxMap)];
2866 }
2867 else
2868 {
2869 pixel.red=(MagickRealType) ScaleMapToQuantum(pixel.red);
2870 pixel.green=(MagickRealType) ScaleMapToQuantum(pixel.green);
2871 pixel.blue=(MagickRealType) ScaleMapToQuantum(pixel.blue);
2872 }
2873 image->colormap[i].red=ClampToQuantum(pixel.red);
2874 image->colormap[i].green=ClampToQuantum(pixel.green);
2875 image->colormap[i].blue=ClampToQuantum(pixel.blue);
2876 }
2877 (void) SyncImage(image);
2878 break;
2879 }
2880 }
2881 /*
2882 Relinquish resources.
2883 */
2884 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2885 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2886 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2887 if (SetImageColorspace(image,sRGBColorspace) == MagickFalse)
2888 return(MagickFalse);
2889 return(MagickTrue);
2890}