2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
13 % MagickCore Image Colorspace Methods %
20 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/property.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/image.h"
54 #include "magick/image-private.h"
55 #include "magick/gem.h"
56 #include "magick/memory_.h"
57 #include "magick/monitor.h"
58 #include "magick/monitor-private.h"
59 #include "magick/pixel-private.h"
60 #include "magick/quantize.h"
61 #include "magick/quantum.h"
62 #include "magick/string_.h"
63 #include "magick/string-private.h"
64 #include "magick/utility.h"
69 typedef struct _TransformPacket
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 + R G B T r a n s f o r m I m a g e %
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88 % RGBTransformImage() converts the reference image from RGB to an alternate
89 % colorspace. The transformation matrices are not the standard ones: the
90 % weights are rescaled to normalized the range of the transformed values to
91 % be [0..QuantumRange].
93 % The format of the RGBTransformImage method is:
95 % MagickBooleanType RGBTransformImage(Image *image,
96 % const ColorspaceType colorspace)
98 % A description of each parameter follows:
100 % o image: the image.
102 % o colorspace: the colorspace to transform the image to.
106 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
107 const Quantum blue,double *X,double *Y,double *Z)
114 assert(X != (double *) NULL);
115 assert(Y != (double *) NULL);
116 assert(Z != (double *) NULL);
118 g=QuantumScale*green;
120 *X=0.4124240*r+0.3575790*g+0.1804640*b;
121 *Y=0.2126560*r+0.7151580*g+0.0721856*b;
122 *Z=0.0193324*r+0.1191930*g+0.9504440*b;
125 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
126 double *L,double *a,double *b)
133 assert(L != (double *) NULL);
134 assert(a != (double *) NULL);
135 assert(b != (double *) NULL);
137 if (x > (216/24389.0))
140 x=(7.787*x)+(16.0/116.0);
142 if (y > (216/24389.0))
145 y=(7.787*y)+(16.0/116.0);
147 if (z > (216/24389.0))
150 z=(7.787*z)+(16.0/116.0);
151 *L=0.5*((1.160*y)-0.160+1.0);
152 *a=0.5*(5.000*(x-y)+1.0);
153 *b=0.5*(2.000*(y-z)+1.0);
156 MagickExport MagickBooleanType RGBTransformImage(Image *image,
157 const ColorspaceType colorspace)
159 #define RGBTransformImageTag "RGBTransform/Image"
186 assert(image != (Image *) NULL);
187 assert(image->signature == MagickSignature);
188 if (image->debug != MagickFalse)
189 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
190 assert(colorspace != RGBColorspace);
191 assert(colorspace != TransparentColorspace);
192 assert(colorspace != UndefinedColorspace);
193 switch (image->colorspace)
196 case Rec601LumaColorspace:
197 case Rec709LumaColorspace:
199 case TransparentColorspace:
203 (void) TransformImageColorspace(image,image->colorspace);
207 if (SetImageColorspace(image,colorspace) == MagickFalse)
211 exception=(&image->exception);
217 Convert RGB to CMY colorspace.
219 if (image->storage_class == PseudoClass)
221 if (SyncImage(image) == MagickFalse)
223 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
226 image_view=AcquireCacheView(image);
227 #if defined(MAGICKCORE_OPENMP_SUPPORT)
228 #pragma omp parallel for schedule(dynamic,4) shared(status)
230 for (y=0; y < (long) image->rows; y++)
238 if (status == MagickFalse)
240 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
242 if (q == (PixelPacket *) NULL)
247 for (x=0; x < (long) image->columns; x++)
249 q->red=ClampToQuantum((MagickRealType) (QuantumRange-q->red));
250 q->green=ClampToQuantum((MagickRealType) (QuantumRange-q->green));
251 q->blue=ClampToQuantum((MagickRealType) (QuantumRange-q->blue));
254 sync=SyncCacheViewAuthenticPixels(image_view,exception);
255 if (sync == MagickFalse)
258 image_view=DestroyCacheView(image_view);
259 image->type=image->matte == MagickFalse ? ColorSeparationType :
260 ColorSeparationMatteType;
269 Convert RGB to CMYK colorspace.
271 if (image->storage_class == PseudoClass)
273 if (SyncImage(image) == MagickFalse)
275 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
278 GetMagickPixelPacket(image,&zero);
279 image_view=AcquireCacheView(image);
280 #if defined(MAGICKCORE_OPENMP_SUPPORT)
281 #pragma omp parallel for schedule(dynamic,4) shared(status)
283 for (y=0; y < (long) image->rows; y++)
297 if (status == MagickFalse)
299 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
301 if (q == (PixelPacket *) NULL)
306 indexes=GetCacheViewAuthenticIndexQueue(image_view);
308 for (x=0; x < (long) image->columns; x++)
310 SetMagickPixelPacket(image,q,indexes+x,&pixel);
311 ConvertRGBToCMYK(&pixel);
312 SetPixelPacket(image,&pixel,q,indexes+x);
315 sync=SyncCacheViewAuthenticPixels(image_view,exception);
316 if (sync == MagickFalse)
319 image_view=DestroyCacheView(image_view);
320 image->type=image->matte == MagickFalse ? ColorSeparationType :
321 ColorSeparationMatteType;
327 Transform image from RGB to HSB.
329 if (image->storage_class == PseudoClass)
331 if (SyncImage(image) == MagickFalse)
333 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
336 image_view=AcquireCacheView(image);
337 #if defined(MAGICKCORE_OPENMP_SUPPORT)
338 #pragma omp parallel for schedule(dynamic,4) shared(status)
340 for (y=0; y < (long) image->rows; y++)
353 if (status == MagickFalse)
355 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
357 if (q == (PixelPacket *) NULL)
365 for (x=0; x < (long) image->columns; x++)
367 ConvertRGBToHSB(q->red,q->green,q->blue,&hue,&saturation,&brightness);
368 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
369 q->green=ClampToQuantum((MagickRealType) QuantumRange*saturation);
370 q->blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
373 sync=SyncCacheViewAuthenticPixels(image_view,exception);
374 if (sync == MagickFalse)
377 image_view=DestroyCacheView(image_view);
383 Transform image from RGB to HSL.
385 if (image->storage_class == PseudoClass)
387 if (SyncImage(image) == MagickFalse)
389 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
392 image_view=AcquireCacheView(image);
393 #if defined(MAGICKCORE_OPENMP_SUPPORT)
394 #pragma omp parallel for schedule(dynamic,4) shared(status)
396 for (y=0; y < (long) image->rows; y++)
409 if (status == MagickFalse)
411 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
413 if (q == (PixelPacket *) NULL)
421 for (x=0; x < (long) image->columns; x++)
423 ConvertRGBToHSL(q->red,q->green,q->blue,&hue,&saturation,&lightness);
424 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
425 q->green=ClampToQuantum((MagickRealType) QuantumRange*saturation);
426 q->blue=ClampToQuantum((MagickRealType) QuantumRange*lightness);
429 sync=SyncCacheViewAuthenticPixels(image_view,exception);
430 if (sync == MagickFalse)
433 image_view=DestroyCacheView(image_view);
439 Transform image from RGB to HWB.
441 if (image->storage_class == PseudoClass)
443 if (SyncImage(image) == MagickFalse)
445 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
448 image_view=AcquireCacheView(image);
449 #if defined(MAGICKCORE_OPENMP_SUPPORT)
450 #pragma omp parallel for schedule(dynamic,4) shared(status)
452 for (y=0; y < (long) image->rows; y++)
465 if (status == MagickFalse)
467 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
469 if (q == (PixelPacket *) NULL)
477 for (x=0; x < (long) image->columns; x++)
479 ConvertRGBToHWB(q->red,q->green,q->blue,&hue,&whiteness,&blackness);
480 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
481 q->green=ClampToQuantum((MagickRealType) QuantumRange*whiteness);
482 q->blue=ClampToQuantum((MagickRealType) QuantumRange*blackness);
485 sync=SyncCacheViewAuthenticPixels(image_view,exception);
486 if (sync == MagickFalse)
489 image_view=DestroyCacheView(image_view);
495 Transform image from RGB to Lab.
497 if (image->storage_class == PseudoClass)
499 if (SyncImage(image) == MagickFalse)
501 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
504 image_view=AcquireCacheView(image);
505 #if defined(MAGICKCORE_OPENMP_SUPPORT)
506 #pragma omp parallel for schedule(dynamic,4) shared(status)
508 for (y=0; y < (long) image->rows; y++)
524 if (status == MagickFalse)
526 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
528 if (q == (PixelPacket *) NULL)
539 for (x=0; x < (long) image->columns; x++)
541 ConvertRGBToXYZ(q->red,q->green,q->blue,&X,&Y,&Z);
542 ConvertXYZToLab(X,Y,Z,&L,&a,&b);
543 q->red=ClampToQuantum((MagickRealType) QuantumRange*L);
544 q->green=ClampToQuantum((MagickRealType) QuantumRange*a);
545 q->blue=ClampToQuantum((MagickRealType) QuantumRange*b);
548 sync=SyncCacheViewAuthenticPixels(image_view,exception);
549 if (sync == MagickFalse)
552 image_view=DestroyCacheView(image_view);
557 #define ReferenceBlack 95.0
558 #define ReferenceWhite 685.0
559 #define DisplayGamma (1.0/1.7)
575 Transform RGB to Log colorspace.
579 value=GetImageProperty(image,"gamma");
580 if (value != (const char *) NULL)
581 gamma=1.0/StringToDouble(value) != 0.0 ? StringToDouble(value) : 1.0;
582 reference_black=ReferenceBlack;
583 value=GetImageProperty(image,"reference-black");
584 if (value != (const char *) NULL)
585 reference_black=StringToDouble(value);
586 reference_white=ReferenceWhite;
587 value=GetImageProperty(image,"reference-white");
588 if (value != (const char *) NULL)
589 reference_white=StringToDouble(value);
590 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
592 if (logmap == (Quantum *) NULL)
593 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
595 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
597 #if defined(MAGICKCORE_OPENMP_SUPPORT)
598 #pragma omp parallel for schedule(dynamic,4)
600 for (i=0; i <= (long) MaxMap; i++)
601 logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
602 log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
603 0.002/0.6))/1024.0+0.5));
604 image_view=AcquireCacheView(image);
605 #if defined(MAGICKCORE_OPENMP_SUPPORT)
606 #pragma omp parallel for schedule(dynamic,4) shared(status)
608 for (y=0; y < (long) image->rows; y++)
616 if (status == MagickFalse)
618 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
620 if (q == (PixelPacket *) NULL)
625 for (x=(long) image->columns; x != 0; x--)
627 q->red=logmap[ScaleQuantumToMap(q->red)];
628 q->green=logmap[ScaleQuantumToMap(q->green)];
629 q->blue=logmap[ScaleQuantumToMap(q->blue)];
632 sync=SyncCacheViewAuthenticPixels(image_view,exception);
633 if (sync == MagickFalse)
636 image_view=DestroyCacheView(image_view);
637 logmap=(Quantum *) RelinquishMagickMemory(logmap);
646 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
648 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
650 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
652 if ((x_map == (TransformPacket *) NULL) ||
653 (y_map == (TransformPacket *) NULL) ||
654 (z_map == (TransformPacket *) NULL))
655 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
657 (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
663 Initialize OHTA tables:
665 I1 = 0.33333*R+0.33334*G+0.33333*B
666 I2 = 0.50000*R+0.00000*G-0.50000*B
667 I3 =-0.25000*R+0.50000*G-0.25000*B
669 I and Q, normally -0.5 through 0.5, are normalized to the range 0
670 through QuantumRange.
672 primary_info.y=(double) (MaxMap+1.0)/2.0;
673 primary_info.z=(double) (MaxMap+1.0)/2.0;
674 #if defined(MAGICKCORE_OPENMP_SUPPORT)
675 #pragma omp parallel for schedule(dynamic,4)
677 for (i=0; i <= (long) MaxMap; i++)
679 x_map[i].x=0.33333f*(MagickRealType) i;
680 y_map[i].x=0.33334f*(MagickRealType) i;
681 z_map[i].x=0.33333f*(MagickRealType) i;
682 x_map[i].y=0.50000f*(MagickRealType) i;
683 y_map[i].y=0.00000f*(MagickRealType) i;
684 z_map[i].y=(-0.50000f)*(MagickRealType) i;
685 x_map[i].z=(-0.25000f)*(MagickRealType) i;
686 y_map[i].z=0.50000f*(MagickRealType) i;
687 z_map[i].z=(-0.25000f)*(MagickRealType) i;
691 case Rec601LumaColorspace:
695 Initialize Rec601 luma tables:
697 G = 0.29900*R+0.58700*G+0.11400*B
699 #if defined(MAGICKCORE_OPENMP_SUPPORT)
700 #pragma omp parallel for schedule(dynamic,4)
702 for (i=0; i <= (long) MaxMap; i++)
704 x_map[i].x=0.29900f*(MagickRealType) i;
705 y_map[i].x=0.58700f*(MagickRealType) i;
706 z_map[i].x=0.11400f*(MagickRealType) i;
707 x_map[i].y=0.29900f*(MagickRealType) i;
708 y_map[i].y=0.58700f*(MagickRealType) i;
709 z_map[i].y=0.11400f*(MagickRealType) i;
710 x_map[i].z=0.29900f*(MagickRealType) i;
711 y_map[i].z=0.58700f*(MagickRealType) i;
712 z_map[i].z=0.11400f*(MagickRealType) i;
714 image->type=GrayscaleType;
717 case Rec601YCbCrColorspace:
718 case YCbCrColorspace:
721 Initialize YCbCr tables (ITU-R BT.601):
723 Y = 0.299000*R+0.587000*G+0.114000*B
724 Cb= -0.168736*R-0.331264*G+0.500000*B
725 Cr= 0.500000*R-0.418688*G-0.081312*B
727 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
728 through QuantumRange.
730 primary_info.y=(double) (MaxMap+1.0)/2.0;
731 primary_info.z=(double) (MaxMap+1.0)/2.0;
732 #if defined(MAGICKCORE_OPENMP_SUPPORT)
733 #pragma omp parallel for schedule(dynamic,4)
735 for (i=0; i <= (long) MaxMap; i++)
737 x_map[i].x=0.299000f*(MagickRealType) i;
738 y_map[i].x=0.587000f*(MagickRealType) i;
739 z_map[i].x=0.114000f*(MagickRealType) i;
740 x_map[i].y=(-0.168730f)*(MagickRealType) i;
741 y_map[i].y=(-0.331264f)*(MagickRealType) i;
742 z_map[i].y=0.500000f*(MagickRealType) i;
743 x_map[i].z=0.500000f*(MagickRealType) i;
744 y_map[i].z=(-0.418688f)*(MagickRealType) i;
745 z_map[i].z=(-0.081312f)*(MagickRealType) i;
749 case Rec709LumaColorspace:
752 Initialize Rec709 luma tables:
754 G = 0.21260*R+0.71520*G+0.07220*B
756 #if defined(MAGICKCORE_OPENMP_SUPPORT)
757 #pragma omp parallel for schedule(dynamic,4)
759 for (i=0; i <= (long) MaxMap; i++)
761 x_map[i].x=0.21260f*(MagickRealType) i;
762 y_map[i].x=0.71520f*(MagickRealType) i;
763 z_map[i].x=0.07220f*(MagickRealType) i;
764 x_map[i].y=0.21260f*(MagickRealType) i;
765 y_map[i].y=0.71520f*(MagickRealType) i;
766 z_map[i].y=0.07220f*(MagickRealType) i;
767 x_map[i].z=0.21260f*(MagickRealType) i;
768 y_map[i].z=0.71520f*(MagickRealType) i;
769 z_map[i].z=0.07220f*(MagickRealType) i;
773 case Rec709YCbCrColorspace:
776 Initialize YCbCr tables (ITU-R BT.709):
778 Y = 0.212600*R+0.715200*G+0.072200*B
779 Cb= -0.114572*R-0.385428*G+0.500000*B
780 Cr= 0.500000*R-0.454153*G-0.045847*B
782 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
783 through QuantumRange.
785 primary_info.y=(double) (MaxMap+1.0)/2.0;
786 primary_info.z=(double) (MaxMap+1.0)/2.0;
787 #if defined(MAGICKCORE_OPENMP_SUPPORT)
788 #pragma omp parallel for schedule(dynamic,4)
790 for (i=0; i <= (long) MaxMap; i++)
792 x_map[i].x=0.212600f*(MagickRealType) i;
793 y_map[i].x=0.715200f*(MagickRealType) i;
794 z_map[i].x=0.072200f*(MagickRealType) i;
795 x_map[i].y=(-0.114572f)*(MagickRealType) i;
796 y_map[i].y=(-0.385428f)*(MagickRealType) i;
797 z_map[i].y=0.500000f*(MagickRealType) i;
798 x_map[i].z=0.500000f*(MagickRealType) i;
799 y_map[i].z=(-0.454153f)*(MagickRealType) i;
800 z_map[i].z=(-0.045847f)*(MagickRealType) i;
807 Linear RGB to nonlinear sRGB (http://www.w3.org/Graphics/Color/sRGB):
809 R = 1.0*R+0.0*G+0.0*B
810 G = 0.0*R+0.1*G+0.0*B
811 B = 0.0*R+0.0*G+1.0*B
813 #if defined(MAGICKCORE_OPENMP_SUPPORT)
814 #pragma omp parallel for schedule(dynamic,4)
816 for (i=0; i <= (long) MaxMap; i++)
821 v=(MagickRealType) i/(MagickRealType) MaxMap;
822 if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.03928f)
825 v=(MagickRealType) MaxMap*pow((((double) i/MaxMap)+0.055)/1.055,2.4);
841 Initialize CIE XYZ tables (ITU-R 709 RGB):
843 X = 0.4124564*R+0.3575761*G+0.1804375*B
844 Y = 0.2126729*R+0.7151522*G+0.0721750*B
845 Z = 0.0193339*R+0.1191920*G+0.9503041*B
847 #if defined(MAGICKCORE_OPENMP_SUPPORT)
848 #pragma omp parallel for schedule(dynamic,4)
850 for (i=0; i <= (long) MaxMap; i++)
852 x_map[i].x=0.4124564f*(MagickRealType) i;
853 y_map[i].x=0.3575761f*(MagickRealType) i;
854 z_map[i].x=0.1804375f*(MagickRealType) i;
855 x_map[i].y=0.2126729f*(MagickRealType) i;
856 y_map[i].y=0.7151522f*(MagickRealType) i;
857 z_map[i].y=0.0721750f*(MagickRealType) i;
858 x_map[i].z=0.0193339f*(MagickRealType) i;
859 y_map[i].z=0.1191920f*(MagickRealType) i;
860 z_map[i].z=0.9503041f*(MagickRealType) i;
867 Initialize YCC tables:
869 Y = 0.29900*R+0.58700*G+0.11400*B
870 C1= -0.29900*R-0.58700*G+0.88600*B
871 C2= 0.70100*R-0.58700*G-0.11400*B
873 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
875 primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
876 primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
877 for (i=0; i <= (long) (0.018*MaxMap); i++)
879 x_map[i].x=0.003962014134275617f*(MagickRealType) i;
880 y_map[i].x=0.007778268551236748f*(MagickRealType) i;
881 z_map[i].x=0.001510600706713781f*(MagickRealType) i;
882 x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
883 y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
884 z_map[i].y=0.007190585689165425f*(MagickRealType) i;
885 x_map[i].z=0.006927257754597858f*(MagickRealType) i;
886 y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
887 z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
889 for ( ; i <= (long) MaxMap; i++)
891 x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
892 y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
893 z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
894 x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
895 y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
896 z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
897 x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
898 y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
899 z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
906 Initialize YIQ tables:
908 Y = 0.29900*R+0.58700*G+0.11400*B
909 I = 0.59600*R-0.27400*G-0.32200*B
910 Q = 0.21100*R-0.52300*G+0.31200*B
912 I and Q, normally -0.5 through 0.5, are normalized to the range 0
913 through QuantumRange.
915 primary_info.y=(double) (MaxMap+1.0)/2.0;
916 primary_info.z=(double) (MaxMap+1.0)/2.0;
917 #if defined(MAGICKCORE_OPENMP_SUPPORT)
918 #pragma omp parallel for schedule(dynamic,4)
920 for (i=0; i <= (long) MaxMap; i++)
922 x_map[i].x=0.29900f*(MagickRealType) i;
923 y_map[i].x=0.58700f*(MagickRealType) i;
924 z_map[i].x=0.11400f*(MagickRealType) i;
925 x_map[i].y=0.59600f*(MagickRealType) i;
926 y_map[i].y=(-0.27400f)*(MagickRealType) i;
927 z_map[i].y=(-0.32200f)*(MagickRealType) i;
928 x_map[i].z=0.21100f*(MagickRealType) i;
929 y_map[i].z=(-0.52300f)*(MagickRealType) i;
930 z_map[i].z=0.31200f*(MagickRealType) i;
934 case YPbPrColorspace:
937 Initialize YPbPr tables (ITU-R BT.601):
939 Y = 0.299000*R+0.587000*G+0.114000*B
940 Pb= -0.168736*R-0.331264*G+0.500000*B
941 Pr= 0.500000*R-0.418688*G-0.081312*B
943 Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
944 through QuantumRange.
946 primary_info.y=(double) (MaxMap+1.0)/2.0;
947 primary_info.z=(double) (MaxMap+1.0)/2.0;
948 #if defined(MAGICKCORE_OPENMP_SUPPORT)
949 #pragma omp parallel for schedule(dynamic,4)
951 for (i=0; i <= (long) MaxMap; i++)
953 x_map[i].x=0.299000f*(MagickRealType) i;
954 y_map[i].x=0.587000f*(MagickRealType) i;
955 z_map[i].x=0.114000f*(MagickRealType) i;
956 x_map[i].y=(-0.168736f)*(MagickRealType) i;
957 y_map[i].y=(-0.331264f)*(MagickRealType) i;
958 z_map[i].y=0.500000f*(MagickRealType) i;
959 x_map[i].z=0.500000f*(MagickRealType) i;
960 y_map[i].z=(-0.418688f)*(MagickRealType) i;
961 z_map[i].z=(-0.081312f)*(MagickRealType) i;
969 Initialize YUV tables:
971 Y = 0.29900*R+0.58700*G+0.11400*B
972 U = -0.14740*R-0.28950*G+0.43690*B
973 V = 0.61500*R-0.51500*G-0.10000*B
975 U and V, normally -0.5 through 0.5, are normalized to the range 0
976 through QuantumRange. Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
978 primary_info.y=(double) (MaxMap+1.0)/2.0;
979 primary_info.z=(double) (MaxMap+1.0)/2.0;
980 #if defined(MAGICKCORE_OPENMP_SUPPORT)
981 #pragma omp parallel for schedule(dynamic,4)
983 for (i=0; i <= (long) MaxMap; i++)
985 x_map[i].x=0.29900f*(MagickRealType) i;
986 y_map[i].x=0.58700f*(MagickRealType) i;
987 z_map[i].x=0.11400f*(MagickRealType) i;
988 x_map[i].y=(-0.14740f)*(MagickRealType) i;
989 y_map[i].y=(-0.28950f)*(MagickRealType) i;
990 z_map[i].y=0.43690f*(MagickRealType) i;
991 x_map[i].z=0.61500f*(MagickRealType) i;
992 y_map[i].z=(-0.51500f)*(MagickRealType) i;
993 z_map[i].z=(-0.10000f)*(MagickRealType) i;
1001 switch (image->storage_class)
1007 Convert DirectClass image.
1009 image_view=AcquireCacheView(image);
1010 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1011 #pragma omp parallel for schedule(dynamic,4) shared(status)
1013 for (y=0; y < (long) image->rows; y++)
1021 register PixelPacket
1024 register unsigned long
1029 if (status == MagickFalse)
1031 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1033 if (q == (PixelPacket *) NULL)
1038 for (x=0; x < (long) image->columns; x++)
1040 red=ScaleQuantumToMap(q->red);
1041 green=ScaleQuantumToMap(q->green);
1042 blue=ScaleQuantumToMap(q->blue);
1043 pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1044 (MagickRealType) primary_info.x;
1045 pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1046 (MagickRealType) primary_info.y;
1047 pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1048 (MagickRealType) primary_info.z;
1049 q->red=ScaleMapToQuantum(pixel.red);
1050 q->green=ScaleMapToQuantum(pixel.green);
1051 q->blue=ScaleMapToQuantum(pixel.blue);
1054 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1055 if (sync == MagickFalse)
1057 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1062 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1063 #pragma omp critical (MagickCore_RGBTransformImage)
1065 proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
1067 if (proceed == MagickFalse)
1071 image_view=DestroyCacheView(image_view);
1076 register unsigned long
1082 Convert PseudoClass image.
1084 image_view=AcquireCacheView(image);
1085 for (i=0; i < (long) image->colors; i++)
1090 red=ScaleQuantumToMap(image->colormap[i].red);
1091 green=ScaleQuantumToMap(image->colormap[i].green);
1092 blue=ScaleQuantumToMap(image->colormap[i].blue);
1093 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1094 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1095 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1096 image->colormap[i].red=ScaleMapToQuantum(pixel.red);
1097 image->colormap[i].green=ScaleMapToQuantum(pixel.green);
1098 image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
1100 image_view=DestroyCacheView(image_view);
1101 (void) SyncImage(image);
1106 Relinquish resources.
1108 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1109 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1110 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1111 if (SetImageColorspace(image,colorspace) == MagickFalse)
1112 return(MagickFalse);
1117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1121 % S e t I m a g e C o l o r s p a c e %
1125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1127 % SetImageColorspace() sets the colorspace member of the Image structure.
1129 % The format of the SetImageColorspace method is:
1131 % MagickBooleanType SetImageColorspace(Image *image,
1132 % const ColorspaceType colorspace)
1134 % A description of each parameter follows:
1136 % o image: the image.
1138 % o colorspace: the colorspace.
1141 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1142 const ColorspaceType colorspace)
1147 if (image->colorspace == colorspace)
1149 image->colorspace=colorspace;
1150 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
1151 image->colorspace=colorspace; /* GRAY colorspace might get reset to RGB */
1152 return(cache == (Cache) NULL ? MagickFalse: MagickTrue);
1156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1160 % T r a n s f o r m I m a g e C o l o r s p a c e %
1164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1166 % TransformImageColorspace() transforms an image colorspace.
1168 % The format of the TransformImageColorspace method is:
1170 % MagickBooleanType TransformImageColorspace(Image *image,
1171 % const ColorspaceType colorspace)
1173 % A description of each parameter follows:
1175 % o image: the image.
1177 % o colorspace: the colorspace.
1180 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1181 const ColorspaceType colorspace)
1186 assert(image != (Image *) NULL);
1187 assert(image->signature == MagickSignature);
1188 if (image->debug != MagickFalse)
1189 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1190 if (colorspace == UndefinedColorspace)
1192 if (SetImageColorspace(image,colorspace) == MagickFalse)
1193 return(MagickFalse);
1196 if (image->colorspace == colorspace)
1198 if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
1199 return(TransformRGBImage(image,image->colorspace));
1201 if ((image->colorspace != RGBColorspace) &&
1202 (image->colorspace != TransparentColorspace) &&
1203 (image->colorspace != GRAYColorspace))
1204 status=TransformRGBImage(image,image->colorspace);
1205 if (RGBTransformImage(image,colorspace) == MagickFalse)
1211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 + T r a n s f o r m R G B I m a g e %
1219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1221 % TransformRGBImage() converts the reference image from an alternate
1222 % colorspace to RGB. The transformation matrices are not the standard ones:
1223 % the weights are rescaled to normalize the range of the transformed values to
1224 % be [0..QuantumRange].
1226 % The format of the TransformRGBImage method is:
1228 % MagickBooleanType TransformRGBImage(Image *image,
1229 % const ColorspaceType colorspace)
1231 % A description of each parameter follows:
1233 % o image: the image.
1235 % o colorspace: the colorspace to transform the image to.
1239 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1240 double *X,double *Y,double *Z)
1247 assert(X != (double *) NULL);
1248 assert(Y != (double *) NULL);
1249 assert(Z != (double *) NULL);
1250 y=((2.0*L-1.0)+0.160)/1.160;
1251 x=(2.0*a-1.0)/5.000+y;
1252 z=y-(2.0*b-1.0)/2.000;
1253 if ((x*x*x) > (216.0/24389.0))
1256 x=(x-16.0/116.0)/7.787;
1257 if ((y*y*y) > (216.0/24389.0))
1260 y=(y-16.0/116.0)/7.787;
1261 if ((z*z*z) > (216.0/24389.0))
1264 z=(z-16.0/116.0)/7.787;
1270 static inline unsigned short RoundToYCC(const MagickRealType value)
1276 return((unsigned short) (value+0.5));
1279 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1280 Quantum *red,Quantum *green,Quantum *blue)
1288 Convert XYZ to RGB colorspace.
1290 assert(red != (Quantum *) NULL);
1291 assert(green != (Quantum *) NULL);
1292 assert(blue != (Quantum *) NULL);
1293 r=3.2407100*x-1.5372600*y-0.4985710*z;
1294 g=(-0.9692580*x+1.8759900*y+0.0415557*z);
1295 b=0.0556352*x-0.2039960*y+1.0570700*z;
1296 *red=ClampToQuantum((MagickRealType) QuantumRange*r);
1297 *green=ClampToQuantum((MagickRealType) QuantumRange*g);
1298 *blue=ClampToQuantum((MagickRealType) QuantumRange*b);
1301 static inline void ConvertCMYKToRGB(MagickPixelPacket *pixel)
1303 pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1304 (QuantumRange-pixel->index)+pixel->index);
1305 pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1306 (QuantumRange-pixel->index)+pixel->index);
1307 pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1308 (QuantumRange-pixel->index)+pixel->index);
1311 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1312 const ColorspaceType colorspace)
1314 #define D50X (0.9642)
1316 #define D50Z (0.8249)
1317 #define TransformRGBImageTag "Transform/Image"
1319 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1320 static const unsigned char
1321 YCCMap[351] = /* Photo CD information beyond 100% white, Gamma 2.2 */
1323 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1324 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
1325 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
1326 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58,
1327 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73,
1328 74, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89,
1329 90, 91, 92, 93, 94, 95, 97, 98, 99, 100, 101, 102, 103, 104,
1330 105, 106, 107, 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
1331 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134,
1332 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
1333 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
1334 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
1335 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
1336 190, 191, 192, 193, 193, 194, 195, 196, 197, 198, 199, 200, 201, 201,
1337 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
1338 214, 215, 215, 216, 217, 218, 218, 219, 220, 221, 221, 222, 223, 224,
1339 224, 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232, 233,
1340 234, 234, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241,
1341 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247,
1342 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
1343 251, 251, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253,
1344 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254,
1345 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255,
1346 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1347 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1373 assert(image != (Image *) NULL);
1374 assert(image->signature == MagickSignature);
1375 if (image->debug != MagickFalse)
1376 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1379 case GRAYColorspace:
1380 case Rec601LumaColorspace:
1381 case Rec709LumaColorspace:
1383 case TransparentColorspace:
1384 case UndefinedColorspace:
1391 exception=(&image->exception);
1397 Transform image from CMY to RGB.
1399 if (image->storage_class == PseudoClass)
1401 if (SyncImage(image) == MagickFalse)
1402 return(MagickFalse);
1403 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1404 return(MagickFalse);
1406 image_view=AcquireCacheView(image);
1407 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1408 #pragma omp parallel for schedule(dynamic,4) shared(status)
1410 for (y=0; y < (long) image->rows; y++)
1418 register PixelPacket
1421 if (status == MagickFalse)
1423 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1425 if (q == (PixelPacket *) NULL)
1430 for (x=0; x < (long) image->columns; x++)
1432 q->red=ClampToQuantum((MagickRealType) (QuantumRange-q->red));
1433 q->green=ClampToQuantum((MagickRealType) (QuantumRange-q->green));
1434 q->blue=ClampToQuantum((MagickRealType) (QuantumRange-q->blue));
1437 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1438 if (sync == MagickFalse)
1441 image_view=DestroyCacheView(image_view);
1442 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1443 return(MagickFalse);
1446 case CMYKColorspace:
1452 Transform image from CMYK to RGB.
1454 if (image->storage_class == PseudoClass)
1456 if (SyncImage(image) == MagickFalse)
1457 return(MagickFalse);
1458 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1459 return(MagickFalse);
1461 GetMagickPixelPacket(image,&zero);
1462 image_view=AcquireCacheView(image);
1463 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1464 #pragma omp parallel for schedule(dynamic,4) shared(status)
1466 for (y=0; y < (long) image->rows; y++)
1474 register IndexPacket
1480 register PixelPacket
1483 if (status == MagickFalse)
1485 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1487 if (q == (PixelPacket *) NULL)
1492 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1494 for (x=0; x < (long) image->columns; x++)
1496 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1497 ConvertCMYKToRGB(&pixel);
1498 SetPixelPacket(image,&pixel,q,indexes+x);
1501 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1502 if (sync == MagickFalse)
1505 image_view=DestroyCacheView(image_view);
1506 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1507 return(MagickFalse);
1513 Transform image from HSB to RGB.
1515 if (image->storage_class == PseudoClass)
1517 if (SyncImage(image) == MagickFalse)
1518 return(MagickFalse);
1519 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1520 return(MagickFalse);
1522 image_view=AcquireCacheView(image);
1523 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1524 #pragma omp parallel for schedule(dynamic,4) shared(status)
1526 for (y=0; y < (long) image->rows; y++)
1539 register PixelPacket
1542 if (status == MagickFalse)
1544 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1546 if (q == (PixelPacket *) NULL)
1551 for (x=0; x < (long) image->columns; x++)
1553 hue=(double) (QuantumScale*q->red);
1554 saturation=(double) (QuantumScale*q->green);
1555 brightness=(double) (QuantumScale*q->blue);
1556 ConvertHSBToRGB(hue,saturation,brightness,&q->red,&q->green,&q->blue);
1559 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1560 if (sync == MagickFalse)
1563 image_view=DestroyCacheView(image_view);
1564 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1565 return(MagickFalse);
1571 Transform image from HSL to RGB.
1573 if (image->storage_class == PseudoClass)
1575 if (SyncImage(image) == MagickFalse)
1576 return(MagickFalse);
1577 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1578 return(MagickFalse);
1580 image_view=AcquireCacheView(image);
1581 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1582 #pragma omp parallel for schedule(dynamic,4) shared(status)
1584 for (y=0; y < (long) image->rows; y++)
1597 register PixelPacket
1600 if (status == MagickFalse)
1602 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1604 if (q == (PixelPacket *) NULL)
1609 for (x=0; x < (long) image->columns; x++)
1611 hue=(double) (QuantumScale*q->red);
1612 saturation=(double) (QuantumScale*q->green);
1613 lightness=(double) (QuantumScale*q->blue);
1614 ConvertHSLToRGB(hue,saturation,lightness,&q->red,&q->green,&q->blue);
1617 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1618 if (sync == MagickFalse)
1621 image_view=DestroyCacheView(image_view);
1622 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1623 return(MagickFalse);
1629 Transform image from HWB to RGB.
1631 if (image->storage_class == PseudoClass)
1633 if (SyncImage(image) == MagickFalse)
1634 return(MagickFalse);
1635 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1636 return(MagickFalse);
1638 image_view=AcquireCacheView(image);
1639 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1640 #pragma omp parallel for schedule(dynamic,4) shared(status)
1642 for (y=0; y < (long) image->rows; y++)
1655 register PixelPacket
1658 if (status == MagickFalse)
1660 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1662 if (q == (PixelPacket *) NULL)
1667 for (x=0; x < (long) image->columns; x++)
1669 hue=(double) (QuantumScale*q->red);
1670 whiteness=(double) (QuantumScale*q->green);
1671 blackness=(double) (QuantumScale*q->blue);
1672 ConvertHWBToRGB(hue,whiteness,blackness,&q->red,&q->green,&q->blue);
1675 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1676 if (sync == MagickFalse)
1679 image_view=DestroyCacheView(image_view);
1680 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1681 return(MagickFalse);
1687 Transform image from Lab to RGB.
1689 if (image->storage_class == PseudoClass)
1691 if (SyncImage(image) == MagickFalse)
1692 return(MagickFalse);
1693 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1694 return(MagickFalse);
1696 image_view=AcquireCacheView(image);
1697 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1698 #pragma omp parallel for schedule(dynamic,4) shared(status)
1700 for (y=0; y < (long) image->rows; y++)
1716 register PixelPacket
1719 if (status == MagickFalse)
1721 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1723 if (q == (PixelPacket *) NULL)
1731 for (x=0; x < (long) image->columns; x++)
1733 L=QuantumScale*q->red;
1734 a=QuantumScale*q->green;
1735 b=QuantumScale*q->blue;
1736 ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
1737 ConvertXYZToRGB(X,Y,Z,&q->red,&q->green,&q->blue);
1740 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1741 if (sync == MagickFalse)
1744 image_view=DestroyCacheView(image_view);
1745 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1746 return(MagickFalse);
1765 Transform Log to RGB colorspace.
1769 value=GetImageProperty(image,"gamma");
1770 if (value != (const char *) NULL)
1771 gamma=1.0/StringToDouble(value) != 0.0 ? StringToDouble(value) : 1.0;
1772 reference_black=ReferenceBlack;
1773 value=GetImageProperty(image,"reference-black");
1774 if (value != (const char *) NULL)
1775 reference_black=StringToDouble(value);
1776 reference_white=ReferenceWhite;
1777 value=GetImageProperty(image,"reference-white");
1778 if (value != (const char *) NULL)
1779 reference_white=StringToDouble(value);
1780 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1782 if (logmap == (Quantum *) NULL)
1783 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1785 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
1787 for (i=0; i <= (long) (reference_black*MaxMap/1024.0); i++)
1788 logmap[i]=(Quantum) 0;
1789 for ( ; i < (long) (reference_white*MaxMap/1024.0); i++)
1790 logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
1791 (pow(10.0,(1024.0*i/MaxMap-reference_white)*
1792 (gamma/density)*0.002/0.6)-black));
1793 for ( ; i <= (long) MaxMap; i++)
1794 logmap[i]=(Quantum) QuantumRange;
1795 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1796 return(MagickFalse);
1797 image_view=AcquireCacheView(image);
1798 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1799 #pragma omp parallel for schedule(dynamic,4) shared(status)
1801 for (y=0; y < (long) image->rows; y++)
1809 register PixelPacket
1812 if (status == MagickFalse)
1814 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1816 if (q == (PixelPacket *) NULL)
1821 for (x=(long) image->columns; x != 0; x--)
1823 q->red=logmap[ScaleQuantumToMap(q->red)];
1824 q->green=logmap[ScaleQuantumToMap(q->green)];
1825 q->blue=logmap[ScaleQuantumToMap(q->blue)];
1828 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1829 if (sync == MagickFalse)
1832 image_view=DestroyCacheView(image_view);
1833 logmap=(Quantum *) RelinquishMagickMemory(logmap);
1834 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1835 return(MagickFalse);
1842 Allocate the tables.
1844 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1846 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1848 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1850 if ((x_map == (TransformPacket *) NULL) ||
1851 (y_map == (TransformPacket *) NULL) ||
1852 (z_map == (TransformPacket *) NULL))
1854 if (z_map != (TransformPacket *) NULL)
1855 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1856 if (y_map != (TransformPacket *) NULL)
1857 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1858 if (x_map != (TransformPacket *) NULL)
1859 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1860 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1865 case OHTAColorspace:
1868 Initialize OHTA tables:
1870 R = I1+1.00000*I2-0.66668*I3
1871 G = I1+0.00000*I2+1.33333*I3
1872 B = I1-1.00000*I2-0.66668*I3
1874 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
1875 through QuantumRange.
1877 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1878 #pragma omp parallel for schedule(dynamic,4)
1880 for (i=0; i <= (long) MaxMap; i++)
1882 x_map[i].x=(MagickRealType) i;
1883 y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
1885 z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1887 x_map[i].y=(MagickRealType) i;
1888 y_map[i].y=0.000000f;
1889 z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
1891 x_map[i].z=(MagickRealType) i;
1892 y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1894 z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1899 case Rec601YCbCrColorspace:
1900 case YCbCrColorspace:
1903 Initialize YCbCr tables:
1906 G = Y-0.344136*Cb-0.714136*Cr
1909 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1910 through QuantumRange.
1912 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1913 #pragma omp parallel for schedule(dynamic,4)
1915 for (i=0; i <= (long) MaxMap; i++)
1917 x_map[i].x=(MagickRealType) i;
1918 y_map[i].x=0.000000f;
1919 z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
1920 (MagickRealType) MaxMap);
1921 x_map[i].y=(MagickRealType) i;
1922 y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
1923 (MagickRealType) MaxMap);
1924 z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
1925 (MagickRealType) MaxMap);
1926 x_map[i].z=(MagickRealType) i;
1927 y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
1928 (MagickRealType) MaxMap);
1929 z_map[i].z=0.000000f;
1933 case Rec709YCbCrColorspace:
1936 Initialize YCbCr tables:
1939 G = Y-0.187324*Cb-0.468124*Cr
1942 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1943 through QuantumRange.
1945 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1946 #pragma omp parallel for schedule(dynamic,4)
1948 for (i=0; i <= (long) MaxMap; i++)
1950 x_map[i].x=(MagickRealType) i;
1951 y_map[i].x=0.000000f;
1952 z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
1953 (MagickRealType) MaxMap);
1954 x_map[i].y=(MagickRealType) i;
1955 y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
1956 (MagickRealType) MaxMap);
1957 z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
1958 (MagickRealType) MaxMap);
1959 x_map[i].z=(MagickRealType) i;
1960 y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
1961 (MagickRealType) MaxMap);
1962 z_map[i].z=0.00000f;
1966 case sRGBColorspace:
1969 Nonlinear sRGB to linear RGB.
1971 R = 1.0*R+0.0*G+0.0*B
1972 G = 0.0*R+1.0*G+0.0*B
1973 B = 0.0*R+0.0*G+1.0*B
1975 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1976 #pragma omp parallel for schedule(dynamic,4)
1978 for (i=0; i <= (long) MaxMap; i++)
1980 x_map[i].x=1.0f*(MagickRealType) i;
1981 y_map[i].x=0.0f*(MagickRealType) i;
1982 z_map[i].x=0.0f*(MagickRealType) i;
1983 x_map[i].y=0.0f*(MagickRealType) i;
1984 y_map[i].y=1.0f*(MagickRealType) i;
1985 z_map[i].y=0.0f*(MagickRealType) i;
1986 x_map[i].z=0.0f*(MagickRealType) i;
1987 y_map[i].z=0.0f*(MagickRealType) i;
1988 z_map[i].z=1.0f*(MagickRealType) i;
1995 Initialize CIE XYZ tables (ITU R-709 RGB):
1997 R = 3.2404542*X-1.5371385*Y-0.4985314*Z
1998 G = -0.9692660*X+1.8760108*Y+0.0415560*Z
1999 B = 0.0556434*X-0.2040259*Y+1.057225*Z
2001 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2002 #pragma omp parallel for schedule(dynamic,4)
2004 for (i=0; i <= (long) MaxMap; i++)
2006 x_map[i].x=3.2404542f*(MagickRealType) i;
2007 x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2008 x_map[i].z=0.0556434f*(MagickRealType) i;
2009 y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2010 y_map[i].y=1.8760108f*(MagickRealType) i;
2011 y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2012 z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2013 z_map[i].y=0.0415560f*(MagickRealType) i;
2014 z_map[i].z=1.0572252f*(MagickRealType) i;
2021 Initialize YCC tables:
2024 G = Y-0.317038*C1-0.682243*C2
2027 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
2029 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2030 #pragma omp parallel for schedule(dynamic,4)
2032 for (i=0; i <= (long) MaxMap; i++)
2034 x_map[i].x=1.3584000f*(MagickRealType) i;
2035 y_map[i].x=0.0000000f;
2036 z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2037 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2038 x_map[i].y=1.3584000f*(MagickRealType) i;
2039 y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2040 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2041 z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2042 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2043 x_map[i].z=1.3584000f*(MagickRealType) i;
2044 y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2045 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2046 z_map[i].z=0.0000000f;
2053 Initialize YIQ tables:
2055 R = Y+0.95620*I+0.62140*Q
2056 G = Y-0.27270*I-0.64680*Q
2057 B = Y-1.10370*I+1.70060*Q
2059 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2060 through QuantumRange.
2062 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2063 #pragma omp parallel for schedule(dynamic,4)
2065 for (i=0; i <= (long) MaxMap; i++)
2067 x_map[i].x=(MagickRealType) i;
2068 y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2070 z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2072 x_map[i].y=(MagickRealType) i;
2073 y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2075 z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2077 x_map[i].z=(MagickRealType) i;
2078 y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2080 z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2085 case YPbPrColorspace:
2088 Initialize YPbPr tables:
2091 G = Y-0.344136*C1+0.714136*C2
2094 Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2095 through QuantumRange.
2097 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2098 #pragma omp parallel for schedule(dynamic,4)
2100 for (i=0; i <= (long) MaxMap; i++)
2102 x_map[i].x=(MagickRealType) i;
2103 y_map[i].x=0.000000f;
2104 z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2106 x_map[i].y=(MagickRealType) i;
2107 y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2109 z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2111 x_map[i].z=(MagickRealType) i;
2112 y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2114 z_map[i].z=0.00000f;
2122 Initialize YUV tables:
2125 G = Y-0.39380*U-0.58050*V
2128 U and V, normally -0.5 through 0.5, must be normalized to the range 0
2129 through QuantumRange.
2131 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2132 #pragma omp parallel for schedule(dynamic,4)
2134 for (i=0; i <= (long) MaxMap; i++)
2136 x_map[i].x=(MagickRealType) i;
2137 y_map[i].x=0.00000f;
2138 z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2140 x_map[i].y=(MagickRealType) i;
2141 y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2143 z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2145 x_map[i].z=(MagickRealType) i;
2146 y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2148 z_map[i].z=0.00000f;
2156 switch (image->storage_class)
2162 Convert DirectClass image.
2164 image_view=AcquireCacheView(image);
2165 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2166 #pragma omp parallel for schedule(dynamic,4) shared(status)
2168 for (y=0; y < (long) image->rows; y++)
2179 register PixelPacket
2182 if (status == MagickFalse)
2184 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2186 if (q == (PixelPacket *) NULL)
2191 for (x=0; x < (long) image->columns; x++)
2193 register unsigned long
2198 red=ScaleQuantumToMap(q->red);
2199 green=ScaleQuantumToMap(q->green);
2200 blue=ScaleQuantumToMap(q->blue);
2201 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2202 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2203 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2208 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2209 pixel.red=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2210 255.0*QuantumScale*pixel.red)]);
2211 pixel.green=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2212 255.0*QuantumScale*pixel.green)]);
2213 pixel.blue=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2214 255.0*QuantumScale*pixel.blue)]);
2218 case sRGBColorspace:
2220 if ((QuantumScale*pixel.red) <= 0.0031308)
2223 pixel.red=(MagickRealType) QuantumRange*(1.055*
2224 pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2225 if ((QuantumScale*pixel.green) <= 0.0031308)
2226 pixel.green*=12.92f;
2228 pixel.green=(MagickRealType) QuantumRange*(1.055*
2229 pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2230 if ((QuantumScale*pixel.blue) <= 0.0031308)
2233 pixel.blue=(MagickRealType) QuantumRange*(1.055*
2234 pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2240 q->red=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2242 q->green=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2244 q->blue=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2248 sync=SyncCacheViewAuthenticPixels(image_view,exception);
2249 if (sync == MagickFalse)
2251 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2256 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2257 #pragma omp critical (MagickCore_TransformRGBImage)
2259 proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
2261 if (proceed == MagickFalse)
2265 image_view=DestroyCacheView(image_view);
2271 Convert PseudoClass image.
2273 image_view=AcquireCacheView(image);
2274 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2275 #pragma omp parallel for schedule(dynamic,4) shared(status)
2277 for (i=0; i < (long) image->colors; i++)
2282 register unsigned long
2287 red=ScaleQuantumToMap(image->colormap[i].red);
2288 green=ScaleQuantumToMap(image->colormap[i].green);
2289 blue=ScaleQuantumToMap(image->colormap[i].blue);
2290 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2291 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2292 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2297 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2298 image->colormap[i].red=ScaleCharToQuantum(YCCMap[RoundToYCC(
2299 255.0*QuantumScale*pixel.red)]);
2300 image->colormap[i].green=ScaleCharToQuantum(YCCMap[RoundToYCC(
2301 255.0*QuantumScale*pixel.green)]);
2302 image->colormap[i].blue=ScaleCharToQuantum(YCCMap[RoundToYCC(
2303 255.0*QuantumScale*pixel.blue)]);
2307 case sRGBColorspace:
2309 if ((QuantumScale*pixel.red) <= 0.0031308)
2312 pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2313 pixel.red,(1.0/2.4))-0.055);
2314 if ((QuantumScale*pixel.green) <= 0.0031308)
2315 pixel.green*=12.92f;
2317 pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2318 pixel.green,(1.0/2.4))-0.055);
2319 if ((QuantumScale*pixel.blue) <= 0.0031308)
2322 pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2323 pixel.blue,(1.0/2.4))-0.055);
2327 image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
2328 QuantumScale*pixel.red);
2329 image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
2330 QuantumScale*pixel.green);
2331 image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
2332 QuantumScale*pixel.blue);
2337 image_view=DestroyCacheView(image_view);
2338 (void) SyncImage(image);
2343 Relinquish resources.
2345 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2346 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2347 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2348 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2349 return(MagickFalse);