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