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);
119 r=pow((r+0.055)/1.055,2.4);
122 g=QuantumScale*green;
124 g=pow((g+0.055)/1.055,2.4);
129 b=pow((b+0.055)/1.055,2.4);
132 *X=0.4124240*r+0.3575790*g+0.1804640*b;
133 *Y=0.2126560*r+0.7151580*g+0.0721856*b;
134 *Z=0.0193324*r+0.1191930*g+0.9504440*b;
137 static double LabF1(double alpha)
140 if (alpha <= ((24.0/116.0)*(24.0/116.0)*(24.0/116.0)))
141 return((841.0/108.0)*alpha+(16.0/116.0));
142 return(pow(alpha,1.0/3.0));
145 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
146 double *L,double *a,double *b)
148 #define D50X (0.9642)
150 #define D50Z (0.8249)
157 assert(L != (double *) NULL);
158 assert(a != (double *) NULL);
159 assert(b != (double *) NULL);
163 if ((X == 0.0) && (Y == 0.0) && (Z == 0.0))
168 *L=(116.0*fy-16.0)/100.0;
169 *a=(500.0*(fx-fy))/255.0;
172 *b=(200.0*(fy-fz))/255.0;
177 MagickExport MagickBooleanType RGBTransformImage(Image *image,
178 const ColorspaceType colorspace)
180 #define RGBTransformImageTag "RGBTransform/Image"
209 assert(image != (Image *) NULL);
210 assert(image->signature == MagickSignature);
211 if (image->debug != MagickFalse)
212 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
213 assert(colorspace != RGBColorspace);
214 assert(colorspace != TransparentColorspace);
215 assert(colorspace != UndefinedColorspace);
216 switch (image->colorspace)
219 case Rec601LumaColorspace:
220 case Rec709LumaColorspace:
222 case TransparentColorspace:
226 (void) TransformImageColorspace(image,image->colorspace);
230 if (SetImageColorspace(image,colorspace) == MagickFalse)
234 exception=(&image->exception);
240 Convert RGB to CMY colorspace.
242 if (image->storage_class == PseudoClass)
244 if (SyncImage(image) == MagickFalse)
246 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
249 image_view=AcquireCacheView(image);
250 #if defined(MAGICKCORE_OPENMP_SUPPORT)
251 #pragma omp parallel for schedule(dynamic,4) shared(status)
253 for (y=0; y < (ssize_t) image->rows; y++)
261 if (status == MagickFalse)
263 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
265 if (q == (PixelPacket *) NULL)
270 for (x=0; x < (ssize_t) image->columns; x++)
272 q->red=ClampToQuantum((MagickRealType) (QuantumRange-q->red));
273 q->green=ClampToQuantum((MagickRealType) (QuantumRange-q->green));
274 q->blue=ClampToQuantum((MagickRealType) (QuantumRange-q->blue));
277 sync=SyncCacheViewAuthenticPixels(image_view,exception);
278 if (sync == MagickFalse)
281 image_view=DestroyCacheView(image_view);
282 image->type=image->matte == MagickFalse ? ColorSeparationType :
283 ColorSeparationMatteType;
292 Convert RGB to CMYK colorspace.
294 if (image->storage_class == PseudoClass)
296 if (SyncImage(image) == MagickFalse)
298 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
301 GetMagickPixelPacket(image,&zero);
302 image_view=AcquireCacheView(image);
303 #if defined(MAGICKCORE_OPENMP_SUPPORT)
304 #pragma omp parallel for schedule(dynamic,4) shared(status)
306 for (y=0; y < (ssize_t) image->rows; y++)
320 if (status == MagickFalse)
322 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
324 if (q == (PixelPacket *) NULL)
329 indexes=GetCacheViewAuthenticIndexQueue(image_view);
331 for (x=0; x < (ssize_t) image->columns; x++)
333 SetMagickPixelPacket(image,q,indexes+x,&pixel);
334 ConvertRGBToCMYK(&pixel);
335 SetPixelPacket(image,&pixel,q,indexes+x);
338 sync=SyncCacheViewAuthenticPixels(image_view,exception);
339 if (sync == MagickFalse)
342 image_view=DestroyCacheView(image_view);
343 image->type=image->matte == MagickFalse ? ColorSeparationType :
344 ColorSeparationMatteType;
350 Transform image from RGB to HSB.
352 if (image->storage_class == PseudoClass)
354 if (SyncImage(image) == MagickFalse)
356 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
359 image_view=AcquireCacheView(image);
360 #if defined(MAGICKCORE_OPENMP_SUPPORT)
361 #pragma omp parallel for schedule(dynamic,4) shared(status)
363 for (y=0; y < (ssize_t) image->rows; y++)
376 if (status == MagickFalse)
378 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
380 if (q == (PixelPacket *) NULL)
388 for (x=0; x < (ssize_t) image->columns; x++)
390 ConvertRGBToHSB(q->red,q->green,q->blue,&hue,&saturation,&brightness);
391 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
392 q->green=ClampToQuantum((MagickRealType) QuantumRange*saturation);
393 q->blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
396 sync=SyncCacheViewAuthenticPixels(image_view,exception);
397 if (sync == MagickFalse)
400 image_view=DestroyCacheView(image_view);
406 Transform image from RGB to HSL.
408 if (image->storage_class == PseudoClass)
410 if (SyncImage(image) == MagickFalse)
412 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
415 image_view=AcquireCacheView(image);
416 #if defined(MAGICKCORE_OPENMP_SUPPORT)
417 #pragma omp parallel for schedule(dynamic,4) shared(status)
419 for (y=0; y < (ssize_t) image->rows; y++)
432 if (status == MagickFalse)
434 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
436 if (q == (PixelPacket *) NULL)
444 for (x=0; x < (ssize_t) image->columns; x++)
446 ConvertRGBToHSL(q->red,q->green,q->blue,&hue,&saturation,&lightness);
447 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
448 q->green=ClampToQuantum((MagickRealType) QuantumRange*saturation);
449 q->blue=ClampToQuantum((MagickRealType) QuantumRange*lightness);
452 sync=SyncCacheViewAuthenticPixels(image_view,exception);
453 if (sync == MagickFalse)
456 image_view=DestroyCacheView(image_view);
462 Transform image from RGB to HWB.
464 if (image->storage_class == PseudoClass)
466 if (SyncImage(image) == MagickFalse)
468 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
471 image_view=AcquireCacheView(image);
472 #if defined(MAGICKCORE_OPENMP_SUPPORT)
473 #pragma omp parallel for schedule(dynamic,4) shared(status)
475 for (y=0; y < (ssize_t) image->rows; y++)
488 if (status == MagickFalse)
490 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
492 if (q == (PixelPacket *) NULL)
500 for (x=0; x < (ssize_t) image->columns; x++)
502 ConvertRGBToHWB(q->red,q->green,q->blue,&hue,&whiteness,&blackness);
503 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
504 q->green=ClampToQuantum((MagickRealType) QuantumRange*whiteness);
505 q->blue=ClampToQuantum((MagickRealType) QuantumRange*blackness);
508 sync=SyncCacheViewAuthenticPixels(image_view,exception);
509 if (sync == MagickFalse)
512 image_view=DestroyCacheView(image_view);
518 Transform image from RGB to Lab.
520 if (image->storage_class == PseudoClass)
522 if (SyncImage(image) == MagickFalse)
524 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
527 image_view=AcquireCacheView(image);
528 #if defined(MAGICKCORE_OPENMP_SUPPORT)
529 #pragma omp parallel for schedule(dynamic,4) shared(status)
531 for (y=0; y < (ssize_t) image->rows; y++)
547 if (status == MagickFalse)
549 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
551 if (q == (PixelPacket *) NULL)
562 for (x=0; x < (ssize_t) image->columns; x++)
564 ConvertRGBToXYZ(q->red,q->green,q->blue,&X,&Y,&Z);
565 ConvertXYZToLab(X,Y,Z,&L,&a,&b);
566 q->red=ClampToQuantum((MagickRealType) QuantumRange*L);
567 q->green=ClampToQuantum((MagickRealType) QuantumRange*a);
568 q->blue=ClampToQuantum((MagickRealType) QuantumRange*b);
571 sync=SyncCacheViewAuthenticPixels(image_view,exception);
572 if (sync == MagickFalse)
575 image_view=DestroyCacheView(image_view);
580 #define DisplayGamma (1.0/1.7)
581 #define FilmGamma 0.6
582 #define ReferenceBlack 95.0
583 #define ReferenceWhite 685.0
600 Transform RGB to Log colorspace.
602 density=DisplayGamma;
604 value=GetImageProperty(image,"gamma");
605 if (value != (const char *) NULL)
606 gamma=1.0/StringToDouble(value) != 0.0 ? StringToDouble(value) : 1.0;
607 film_gamma=FilmGamma;
608 value=GetImageProperty(image,"film-gamma");
609 if (value != (const char *) NULL)
610 film_gamma=StringToDouble(value);
611 reference_black=ReferenceBlack;
612 value=GetImageProperty(image,"reference-black");
613 if (value != (const char *) NULL)
614 reference_black=StringToDouble(value);
615 reference_white=ReferenceWhite;
616 value=GetImageProperty(image,"reference-white");
617 if (value != (const char *) NULL)
618 reference_white=StringToDouble(value);
619 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
621 if (logmap == (Quantum *) NULL)
622 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
624 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
626 #if defined(MAGICKCORE_OPENMP_SUPPORT)
627 #pragma omp parallel for schedule(dynamic,4)
629 for (i=0; i <= (ssize_t) MaxMap; i++)
630 logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
631 log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
632 0.002/film_gamma))/1024.0));
633 image_view=AcquireCacheView(image);
634 #if defined(MAGICKCORE_OPENMP_SUPPORT)
635 #pragma omp parallel for schedule(dynamic,4) shared(status)
637 for (y=0; y < (ssize_t) image->rows; y++)
645 if (status == MagickFalse)
647 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
649 if (q == (PixelPacket *) NULL)
654 for (x=(ssize_t) image->columns; x != 0; x--)
656 q->red=logmap[ScaleQuantumToMap(q->red)];
657 q->green=logmap[ScaleQuantumToMap(q->green)];
658 q->blue=logmap[ScaleQuantumToMap(q->blue)];
661 sync=SyncCacheViewAuthenticPixels(image_view,exception);
662 if (sync == MagickFalse)
665 image_view=DestroyCacheView(image_view);
666 logmap=(Quantum *) RelinquishMagickMemory(logmap);
675 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
677 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
679 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
681 if ((x_map == (TransformPacket *) NULL) ||
682 (y_map == (TransformPacket *) NULL) ||
683 (z_map == (TransformPacket *) NULL))
684 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
686 (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
692 Initialize OHTA tables:
694 I1 = 0.33333*R+0.33334*G+0.33333*B
695 I2 = 0.50000*R+0.00000*G-0.50000*B
696 I3 =-0.25000*R+0.50000*G-0.25000*B
698 I and Q, normally -0.5 through 0.5, are normalized to the range 0
699 through QuantumRange.
701 primary_info.y=(double) (MaxMap+1.0)/2.0;
702 primary_info.z=(double) (MaxMap+1.0)/2.0;
703 #if defined(MAGICKCORE_OPENMP_SUPPORT)
704 #pragma omp parallel for schedule(dynamic,4)
706 for (i=0; i <= (ssize_t) MaxMap; i++)
708 x_map[i].x=0.33333f*(MagickRealType) i;
709 y_map[i].x=0.33334f*(MagickRealType) i;
710 z_map[i].x=0.33333f*(MagickRealType) i;
711 x_map[i].y=0.50000f*(MagickRealType) i;
712 y_map[i].y=0.00000f*(MagickRealType) i;
713 z_map[i].y=(-0.50000f)*(MagickRealType) i;
714 x_map[i].z=(-0.25000f)*(MagickRealType) i;
715 y_map[i].z=0.50000f*(MagickRealType) i;
716 z_map[i].z=(-0.25000f)*(MagickRealType) i;
720 case Rec601LumaColorspace:
724 Initialize Rec601 luma tables:
726 G = 0.29900*R+0.58700*G+0.11400*B
728 #if defined(MAGICKCORE_OPENMP_SUPPORT)
729 #pragma omp parallel for schedule(dynamic,4)
731 for (i=0; i <= (ssize_t) MaxMap; i++)
733 x_map[i].x=0.29900f*(MagickRealType) i;
734 y_map[i].x=0.58700f*(MagickRealType) i;
735 z_map[i].x=0.11400f*(MagickRealType) i;
736 x_map[i].y=0.29900f*(MagickRealType) i;
737 y_map[i].y=0.58700f*(MagickRealType) i;
738 z_map[i].y=0.11400f*(MagickRealType) i;
739 x_map[i].z=0.29900f*(MagickRealType) i;
740 y_map[i].z=0.58700f*(MagickRealType) i;
741 z_map[i].z=0.11400f*(MagickRealType) i;
743 image->type=GrayscaleType;
746 case Rec601YCbCrColorspace:
747 case YCbCrColorspace:
750 Initialize YCbCr tables (ITU-R BT.601):
752 Y = 0.299000*R+0.587000*G+0.114000*B
753 Cb= -0.168736*R-0.331264*G+0.500000*B
754 Cr= 0.500000*R-0.418688*G-0.081312*B
756 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
757 through QuantumRange.
759 primary_info.y=(double) (MaxMap+1.0)/2.0;
760 primary_info.z=(double) (MaxMap+1.0)/2.0;
761 #if defined(MAGICKCORE_OPENMP_SUPPORT)
762 #pragma omp parallel for schedule(dynamic,4)
764 for (i=0; i <= (ssize_t) MaxMap; i++)
766 x_map[i].x=0.299000f*(MagickRealType) i;
767 y_map[i].x=0.587000f*(MagickRealType) i;
768 z_map[i].x=0.114000f*(MagickRealType) i;
769 x_map[i].y=(-0.168730f)*(MagickRealType) i;
770 y_map[i].y=(-0.331264f)*(MagickRealType) i;
771 z_map[i].y=0.500000f*(MagickRealType) i;
772 x_map[i].z=0.500000f*(MagickRealType) i;
773 y_map[i].z=(-0.418688f)*(MagickRealType) i;
774 z_map[i].z=(-0.081312f)*(MagickRealType) i;
778 case Rec709LumaColorspace:
781 Initialize Rec709 luma tables:
783 G = 0.21260*R+0.71520*G+0.07220*B
785 #if defined(MAGICKCORE_OPENMP_SUPPORT)
786 #pragma omp parallel for schedule(dynamic,4)
788 for (i=0; i <= (ssize_t) MaxMap; i++)
790 x_map[i].x=0.21260f*(MagickRealType) i;
791 y_map[i].x=0.71520f*(MagickRealType) i;
792 z_map[i].x=0.07220f*(MagickRealType) i;
793 x_map[i].y=0.21260f*(MagickRealType) i;
794 y_map[i].y=0.71520f*(MagickRealType) i;
795 z_map[i].y=0.07220f*(MagickRealType) i;
796 x_map[i].z=0.21260f*(MagickRealType) i;
797 y_map[i].z=0.71520f*(MagickRealType) i;
798 z_map[i].z=0.07220f*(MagickRealType) i;
802 case Rec709YCbCrColorspace:
805 Initialize YCbCr tables (ITU-R BT.709):
807 Y = 0.212600*R+0.715200*G+0.072200*B
808 Cb= -0.114572*R-0.385428*G+0.500000*B
809 Cr= 0.500000*R-0.454153*G-0.045847*B
811 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
812 through QuantumRange.
814 primary_info.y=(double) (MaxMap+1.0)/2.0;
815 primary_info.z=(double) (MaxMap+1.0)/2.0;
816 #if defined(MAGICKCORE_OPENMP_SUPPORT)
817 #pragma omp parallel for schedule(dynamic,4)
819 for (i=0; i <= (ssize_t) MaxMap; i++)
821 x_map[i].x=0.212600f*(MagickRealType) i;
822 y_map[i].x=0.715200f*(MagickRealType) i;
823 z_map[i].x=0.072200f*(MagickRealType) i;
824 x_map[i].y=(-0.114572f)*(MagickRealType) i;
825 y_map[i].y=(-0.385428f)*(MagickRealType) i;
826 z_map[i].y=0.500000f*(MagickRealType) i;
827 x_map[i].z=0.500000f*(MagickRealType) i;
828 y_map[i].z=(-0.454153f)*(MagickRealType) i;
829 z_map[i].z=(-0.045847f)*(MagickRealType) i;
836 Linear sRGB to nonlinear RGB (http://www.w3.org/Graphics/Color/sRGB):
838 R = 1.0*R+0.0*G+0.0*B
839 G = 0.0*R+0.1*G+0.0*B
840 B = 0.0*R+0.0*G+1.0*B
842 #if defined(MAGICKCORE_OPENMP_SUPPORT)
843 #pragma omp parallel for schedule(dynamic,4)
845 for (i=0; i <= (ssize_t) MaxMap; i++)
850 v=(MagickRealType) i/(MagickRealType) MaxMap;
851 if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.04045f)
854 v=(MagickRealType) pow((((double) i/MaxMap)+0.055)/1.055,2.4);
855 x_map[i].x=1.0f*MaxMap*v;
856 y_map[i].x=0.0f*MaxMap*v;
857 z_map[i].x=0.0f*MaxMap*v;
858 x_map[i].y=0.0f*MaxMap*v;
859 y_map[i].y=1.0f*MaxMap*v;
860 z_map[i].y=0.0f*MaxMap*v;
861 x_map[i].z=0.0f*MaxMap*v;
862 y_map[i].z=0.0f*MaxMap*v;
863 z_map[i].z=1.0f*MaxMap*v;
870 Initialize CIE XYZ tables (ITU-R 709 RGB):
872 X = 0.4124564*R+0.3575761*G+0.1804375*B
873 Y = 0.2126729*R+0.7151522*G+0.0721750*B
874 Z = 0.0193339*R+0.1191920*G+0.9503041*B
876 #if defined(MAGICKCORE_OPENMP_SUPPORT)
877 #pragma omp parallel for schedule(dynamic,4)
879 for (i=0; i <= (ssize_t) MaxMap; i++)
881 x_map[i].x=0.4124564f*(MagickRealType) i;
882 y_map[i].x=0.3575761f*(MagickRealType) i;
883 z_map[i].x=0.1804375f*(MagickRealType) i;
884 x_map[i].y=0.2126729f*(MagickRealType) i;
885 y_map[i].y=0.7151522f*(MagickRealType) i;
886 z_map[i].y=0.0721750f*(MagickRealType) i;
887 x_map[i].z=0.0193339f*(MagickRealType) i;
888 y_map[i].z=0.1191920f*(MagickRealType) i;
889 z_map[i].z=0.9503041f*(MagickRealType) i;
896 Initialize YCC tables:
898 Y = 0.29900*R+0.58700*G+0.11400*B
899 C1= -0.29900*R-0.58700*G+0.88600*B
900 C2= 0.70100*R-0.58700*G-0.11400*B
902 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
904 primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
905 primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
906 for (i=0; i <= (ssize_t) (0.018*MaxMap); i++)
908 x_map[i].x=0.003962014134275617f*(MagickRealType) i;
909 y_map[i].x=0.007778268551236748f*(MagickRealType) i;
910 z_map[i].x=0.001510600706713781f*(MagickRealType) i;
911 x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
912 y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
913 z_map[i].y=0.007190585689165425f*(MagickRealType) i;
914 x_map[i].z=0.006927257754597858f*(MagickRealType) i;
915 y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
916 z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
918 for ( ; i <= (ssize_t) MaxMap; i++)
920 x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
921 y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
922 z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
923 x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
924 y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
925 z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
926 x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
927 y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
928 z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
935 Initialize YIQ tables:
937 Y = 0.29900*R+0.58700*G+0.11400*B
938 I = 0.59600*R-0.27400*G-0.32200*B
939 Q = 0.21100*R-0.52300*G+0.31200*B
941 I and Q, normally -0.5 through 0.5, are normalized to the range 0
942 through QuantumRange.
944 primary_info.y=(double) (MaxMap+1.0)/2.0;
945 primary_info.z=(double) (MaxMap+1.0)/2.0;
946 #if defined(MAGICKCORE_OPENMP_SUPPORT)
947 #pragma omp parallel for schedule(dynamic,4)
949 for (i=0; i <= (ssize_t) MaxMap; i++)
951 x_map[i].x=0.29900f*(MagickRealType) i;
952 y_map[i].x=0.58700f*(MagickRealType) i;
953 z_map[i].x=0.11400f*(MagickRealType) i;
954 x_map[i].y=0.59600f*(MagickRealType) i;
955 y_map[i].y=(-0.27400f)*(MagickRealType) i;
956 z_map[i].y=(-0.32200f)*(MagickRealType) i;
957 x_map[i].z=0.21100f*(MagickRealType) i;
958 y_map[i].z=(-0.52300f)*(MagickRealType) i;
959 z_map[i].z=0.31200f*(MagickRealType) i;
963 case YPbPrColorspace:
966 Initialize YPbPr tables (ITU-R BT.601):
968 Y = 0.299000*R+0.587000*G+0.114000*B
969 Pb= -0.168736*R-0.331264*G+0.500000*B
970 Pr= 0.500000*R-0.418688*G-0.081312*B
972 Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
973 through QuantumRange.
975 primary_info.y=(double) (MaxMap+1.0)/2.0;
976 primary_info.z=(double) (MaxMap+1.0)/2.0;
977 #if defined(MAGICKCORE_OPENMP_SUPPORT)
978 #pragma omp parallel for schedule(dynamic,4)
980 for (i=0; i <= (ssize_t) MaxMap; i++)
982 x_map[i].x=0.299000f*(MagickRealType) i;
983 y_map[i].x=0.587000f*(MagickRealType) i;
984 z_map[i].x=0.114000f*(MagickRealType) i;
985 x_map[i].y=(-0.168736f)*(MagickRealType) i;
986 y_map[i].y=(-0.331264f)*(MagickRealType) i;
987 z_map[i].y=0.500000f*(MagickRealType) i;
988 x_map[i].z=0.500000f*(MagickRealType) i;
989 y_map[i].z=(-0.418688f)*(MagickRealType) i;
990 z_map[i].z=(-0.081312f)*(MagickRealType) i;
998 Initialize YUV tables:
1000 Y = 0.29900*R+0.58700*G+0.11400*B
1001 U = -0.14740*R-0.28950*G+0.43690*B
1002 V = 0.61500*R-0.51500*G-0.10000*B
1004 U and V, normally -0.5 through 0.5, are normalized to the range 0
1005 through QuantumRange. Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
1007 primary_info.y=(double) (MaxMap+1.0)/2.0;
1008 primary_info.z=(double) (MaxMap+1.0)/2.0;
1009 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1010 #pragma omp parallel for schedule(dynamic,4)
1012 for (i=0; i <= (ssize_t) MaxMap; i++)
1014 x_map[i].x=0.29900f*(MagickRealType) i;
1015 y_map[i].x=0.58700f*(MagickRealType) i;
1016 z_map[i].x=0.11400f*(MagickRealType) i;
1017 x_map[i].y=(-0.14740f)*(MagickRealType) i;
1018 y_map[i].y=(-0.28950f)*(MagickRealType) i;
1019 z_map[i].y=0.43690f*(MagickRealType) i;
1020 x_map[i].z=0.61500f*(MagickRealType) i;
1021 y_map[i].z=(-0.51500f)*(MagickRealType) i;
1022 z_map[i].z=(-0.10000f)*(MagickRealType) i;
1030 switch (image->storage_class)
1036 Convert DirectClass image.
1038 image_view=AcquireCacheView(image);
1039 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1040 #pragma omp parallel for schedule(dynamic,4) shared(status)
1042 for (y=0; y < (ssize_t) image->rows; y++)
1050 register PixelPacket
1058 if (status == MagickFalse)
1060 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1062 if (q == (PixelPacket *) NULL)
1067 for (x=0; x < (ssize_t) image->columns; x++)
1069 red=ScaleQuantumToMap(q->red);
1070 green=ScaleQuantumToMap(q->green);
1071 blue=ScaleQuantumToMap(q->blue);
1072 pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1073 (MagickRealType) primary_info.x;
1074 pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1075 (MagickRealType) primary_info.y;
1076 pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1077 (MagickRealType) primary_info.z;
1078 q->red=ScaleMapToQuantum(pixel.red);
1079 q->green=ScaleMapToQuantum(pixel.green);
1080 q->blue=ScaleMapToQuantum(pixel.blue);
1083 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1084 if (sync == MagickFalse)
1086 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1091 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1092 #pragma omp critical (MagickCore_RGBTransformImage)
1094 proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
1096 if (proceed == MagickFalse)
1100 image_view=DestroyCacheView(image_view);
1111 Convert PseudoClass image.
1113 image_view=AcquireCacheView(image);
1114 for (i=0; i < (ssize_t) image->colors; i++)
1119 red=ScaleQuantumToMap(image->colormap[i].red);
1120 green=ScaleQuantumToMap(image->colormap[i].green);
1121 blue=ScaleQuantumToMap(image->colormap[i].blue);
1122 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1123 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1124 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1125 image->colormap[i].red=ScaleMapToQuantum(pixel.red);
1126 image->colormap[i].green=ScaleMapToQuantum(pixel.green);
1127 image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
1129 image_view=DestroyCacheView(image_view);
1130 (void) SyncImage(image);
1135 Relinquish resources.
1137 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1138 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1139 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1140 if (SetImageColorspace(image,colorspace) == MagickFalse)
1141 return(MagickFalse);
1146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1150 % S e t I m a g e C o l o r s p a c e %
1154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156 % SetImageColorspace() sets the colorspace member of the Image structure.
1158 % The format of the SetImageColorspace method is:
1160 % MagickBooleanType SetImageColorspace(Image *image,
1161 % const ColorspaceType colorspace)
1163 % A description of each parameter follows:
1165 % o image: the image.
1167 % o colorspace: the colorspace.
1170 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1171 const ColorspaceType colorspace)
1173 image->colorspace=colorspace;
1178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1182 % T r a n s f o r m I m a g e C o l o r s p a c e %
1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188 % TransformImageColorspace() transforms an image colorspace.
1190 % The format of the TransformImageColorspace method is:
1192 % MagickBooleanType TransformImageColorspace(Image *image,
1193 % const ColorspaceType colorspace)
1195 % A description of each parameter follows:
1197 % o image: the image.
1199 % o colorspace: the colorspace.
1202 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1203 const ColorspaceType colorspace)
1208 assert(image != (Image *) NULL);
1209 assert(image->signature == MagickSignature);
1210 if (image->debug != MagickFalse)
1211 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1212 if (colorspace == UndefinedColorspace)
1214 if (SetImageColorspace(image,colorspace) == MagickFalse)
1215 return(MagickFalse);
1218 if (image->colorspace == colorspace)
1220 if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
1221 return(TransformRGBImage(image,image->colorspace));
1223 if ((image->colorspace != RGBColorspace) &&
1224 (image->colorspace != TransparentColorspace) &&
1225 (image->colorspace != GRAYColorspace))
1226 status=TransformRGBImage(image,image->colorspace);
1227 if (RGBTransformImage(image,colorspace) == MagickFalse)
1233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1237 + T r a n s f o r m R G B I m a g e %
1241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1243 % TransformRGBImage() converts the reference image from an alternate
1244 % colorspace to RGB. The transformation matrices are not the standard ones:
1245 % the weights are rescaled to normalize the range of the transformed values to
1246 % be [0..QuantumRange].
1248 % The format of the TransformRGBImage method is:
1250 % MagickBooleanType TransformRGBImage(Image *image,
1251 % const ColorspaceType colorspace)
1253 % A description of each parameter follows:
1255 % o image: the image.
1257 % o colorspace: the colorspace to transform the image to.
1261 static double LabF2(double alpha)
1266 if (alpha > (24.0/116.0))
1267 return(alpha*alpha*alpha);
1268 beta=(108.0/841.0)*(alpha-(16.0/116.0));
1274 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1275 double *X,double *Y,double *Z)
1283 assert(X != (double *) NULL);
1284 assert(Y != (double *) NULL);
1285 assert(Z != (double *) NULL);
1291 y=(100.0*L+16.0)/116.0;
1292 x=y+255.0*0.002*(a > 0.5 ? a-1.0 : a);
1293 z=y-255.0*0.005*(b > 0.5 ? b-1.0 : b);
1299 static inline unsigned short RoundToYCC(const MagickRealType value)
1305 return((unsigned short) (value+0.5));
1308 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1309 Quantum *red,Quantum *green,Quantum *blue)
1317 Convert XYZ to RGB colorspace.
1319 assert(red != (Quantum *) NULL);
1320 assert(green != (Quantum *) NULL);
1321 assert(blue != (Quantum *) NULL);
1322 r=3.2404542*x-1.5371385*y-0.4985314*z;
1323 g=(-0.9692660*x+1.8760108*y+0.0415560*z);
1324 b=0.0556434*x-0.2040259*y+1.0572252*z;
1326 r=1.055*pow(r,1.0/2.4)-0.055;
1330 g=1.055*pow(g,1.0/2.4)-0.055;
1334 b=1.055*pow(b,1.0/2.4)-0.055;
1337 *red=RoundToQuantum((MagickRealType) QuantumRange*r);
1338 *green=RoundToQuantum((MagickRealType) QuantumRange*g);
1339 *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
1342 static inline void ConvertCMYKToRGB(MagickPixelPacket *pixel)
1344 pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1345 (QuantumRange-pixel->index)+pixel->index);
1346 pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1347 (QuantumRange-pixel->index)+pixel->index);
1348 pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1349 (QuantumRange-pixel->index)+pixel->index);
1352 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1353 const ColorspaceType colorspace)
1355 #define D50X (0.9642)
1357 #define D50Z (0.8249)
1358 #define TransformRGBImageTag "Transform/Image"
1360 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1361 static const unsigned char
1362 YCCMap[351] = /* Photo CD information beyond 100% white, Gamma 2.2 */
1364 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1365 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
1366 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
1367 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58,
1368 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73,
1369 74, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89,
1370 90, 91, 92, 93, 94, 95, 97, 98, 99, 100, 101, 102, 103, 104,
1371 105, 106, 107, 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
1372 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134,
1373 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
1374 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
1375 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
1376 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
1377 190, 191, 192, 193, 193, 194, 195, 196, 197, 198, 199, 200, 201, 201,
1378 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
1379 214, 215, 215, 216, 217, 218, 218, 219, 220, 221, 221, 222, 223, 224,
1380 224, 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232, 233,
1381 234, 234, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241,
1382 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247,
1383 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
1384 251, 251, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253,
1385 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254,
1386 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255,
1387 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1388 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1416 assert(image != (Image *) NULL);
1417 assert(image->signature == MagickSignature);
1418 if (image->debug != MagickFalse)
1419 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1422 case GRAYColorspace:
1423 case Rec601LumaColorspace:
1424 case Rec709LumaColorspace:
1426 case TransparentColorspace:
1427 case UndefinedColorspace:
1434 exception=(&image->exception);
1440 Transform image from CMY to RGB.
1442 if (image->storage_class == PseudoClass)
1444 if (SyncImage(image) == MagickFalse)
1445 return(MagickFalse);
1446 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1447 return(MagickFalse);
1449 image_view=AcquireCacheView(image);
1450 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1451 #pragma omp parallel for schedule(dynamic,4) shared(status)
1453 for (y=0; y < (ssize_t) image->rows; y++)
1461 register PixelPacket
1464 if (status == MagickFalse)
1466 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1468 if (q == (PixelPacket *) NULL)
1473 for (x=0; x < (ssize_t) image->columns; x++)
1475 q->red=ClampToQuantum((MagickRealType) (QuantumRange-q->red));
1476 q->green=ClampToQuantum((MagickRealType) (QuantumRange-q->green));
1477 q->blue=ClampToQuantum((MagickRealType) (QuantumRange-q->blue));
1480 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1481 if (sync == MagickFalse)
1484 image_view=DestroyCacheView(image_view);
1485 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1486 return(MagickFalse);
1489 case CMYKColorspace:
1495 Transform image from CMYK to RGB.
1497 if (image->storage_class == PseudoClass)
1499 if (SyncImage(image) == MagickFalse)
1500 return(MagickFalse);
1501 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1502 return(MagickFalse);
1504 GetMagickPixelPacket(image,&zero);
1505 image_view=AcquireCacheView(image);
1506 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1507 #pragma omp parallel for schedule(dynamic,4) shared(status)
1509 for (y=0; y < (ssize_t) image->rows; y++)
1517 register IndexPacket
1523 register PixelPacket
1526 if (status == MagickFalse)
1528 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1530 if (q == (PixelPacket *) NULL)
1535 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1537 for (x=0; x < (ssize_t) image->columns; x++)
1539 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1540 ConvertCMYKToRGB(&pixel);
1541 SetPixelPacket(image,&pixel,q,indexes+x);
1544 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1545 if (sync == MagickFalse)
1548 image_view=DestroyCacheView(image_view);
1549 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1550 return(MagickFalse);
1556 Transform image from HSB to RGB.
1558 if (image->storage_class == PseudoClass)
1560 if (SyncImage(image) == MagickFalse)
1561 return(MagickFalse);
1562 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1563 return(MagickFalse);
1565 image_view=AcquireCacheView(image);
1566 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1567 #pragma omp parallel for schedule(dynamic,4) shared(status)
1569 for (y=0; y < (ssize_t) image->rows; y++)
1582 register PixelPacket
1585 if (status == MagickFalse)
1587 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1589 if (q == (PixelPacket *) NULL)
1594 for (x=0; x < (ssize_t) image->columns; x++)
1596 hue=(double) (QuantumScale*q->red);
1597 saturation=(double) (QuantumScale*q->green);
1598 brightness=(double) (QuantumScale*q->blue);
1599 ConvertHSBToRGB(hue,saturation,brightness,&q->red,&q->green,&q->blue);
1602 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1603 if (sync == MagickFalse)
1606 image_view=DestroyCacheView(image_view);
1607 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1608 return(MagickFalse);
1614 Transform image from HSL to RGB.
1616 if (image->storage_class == PseudoClass)
1618 if (SyncImage(image) == MagickFalse)
1619 return(MagickFalse);
1620 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1621 return(MagickFalse);
1623 image_view=AcquireCacheView(image);
1624 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1625 #pragma omp parallel for schedule(dynamic,4) shared(status)
1627 for (y=0; y < (ssize_t) image->rows; y++)
1640 register PixelPacket
1643 if (status == MagickFalse)
1645 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1647 if (q == (PixelPacket *) NULL)
1652 for (x=0; x < (ssize_t) image->columns; x++)
1654 hue=(double) (QuantumScale*q->red);
1655 saturation=(double) (QuantumScale*q->green);
1656 lightness=(double) (QuantumScale*q->blue);
1657 ConvertHSLToRGB(hue,saturation,lightness,&q->red,&q->green,&q->blue);
1660 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1661 if (sync == MagickFalse)
1664 image_view=DestroyCacheView(image_view);
1665 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1666 return(MagickFalse);
1672 Transform image from HWB to RGB.
1674 if (image->storage_class == PseudoClass)
1676 if (SyncImage(image) == MagickFalse)
1677 return(MagickFalse);
1678 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1679 return(MagickFalse);
1681 image_view=AcquireCacheView(image);
1682 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1683 #pragma omp parallel for schedule(dynamic,4) shared(status)
1685 for (y=0; y < (ssize_t) image->rows; y++)
1698 register PixelPacket
1701 if (status == MagickFalse)
1703 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1705 if (q == (PixelPacket *) NULL)
1710 for (x=0; x < (ssize_t) image->columns; x++)
1712 hue=(double) (QuantumScale*q->red);
1713 whiteness=(double) (QuantumScale*q->green);
1714 blackness=(double) (QuantumScale*q->blue);
1715 ConvertHWBToRGB(hue,whiteness,blackness,&q->red,&q->green,&q->blue);
1718 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1719 if (sync == MagickFalse)
1722 image_view=DestroyCacheView(image_view);
1723 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1724 return(MagickFalse);
1730 Transform image from Lab to RGB.
1732 if (image->storage_class == PseudoClass)
1734 if (SyncImage(image) == MagickFalse)
1735 return(MagickFalse);
1736 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1737 return(MagickFalse);
1739 image_view=AcquireCacheView(image);
1740 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1741 #pragma omp parallel for schedule(dynamic,4) shared(status)
1743 for (y=0; y < (ssize_t) image->rows; y++)
1759 register PixelPacket
1762 if (status == MagickFalse)
1764 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1766 if (q == (PixelPacket *) NULL)
1774 for (x=0; x < (ssize_t) image->columns; x++)
1776 L=QuantumScale*q->red;
1777 a=QuantumScale*q->green;
1778 b=QuantumScale*q->blue;
1779 ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
1780 ConvertXYZToRGB(X,Y,Z,&q->red,&q->green,&q->blue);
1783 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1784 if (sync == MagickFalse)
1787 image_view=DestroyCacheView(image_view);
1788 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1789 return(MagickFalse);
1809 Transform Log to RGB colorspace.
1811 density=DisplayGamma;
1813 value=GetImageProperty(image,"gamma");
1814 if (value != (const char *) NULL)
1815 gamma=1.0/StringToDouble(value) != 0.0 ? StringToDouble(value) : 1.0;
1816 film_gamma=FilmGamma;
1817 value=GetImageProperty(image,"film-gamma");
1818 if (value != (const char *) NULL)
1819 film_gamma=StringToDouble(value);
1820 reference_black=ReferenceBlack;
1821 value=GetImageProperty(image,"reference-black");
1822 if (value != (const char *) NULL)
1823 reference_black=StringToDouble(value);
1824 reference_white=ReferenceWhite;
1825 value=GetImageProperty(image,"reference-white");
1826 if (value != (const char *) NULL)
1827 reference_white=StringToDouble(value);
1828 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1830 if (logmap == (Quantum *) NULL)
1831 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1833 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
1835 for (i=0; i <= (ssize_t) (reference_black*MaxMap/1024.0); i++)
1836 logmap[i]=(Quantum) 0;
1837 for ( ; i < (ssize_t) (reference_white*MaxMap/1024.0); i++)
1838 logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
1839 (pow(10.0,(1024.0*i/MaxMap-reference_white)*
1840 (gamma/density)*0.002/film_gamma)-black));
1841 for ( ; i <= (ssize_t) MaxMap; i++)
1842 logmap[i]=(Quantum) QuantumRange;
1843 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1844 return(MagickFalse);
1845 image_view=AcquireCacheView(image);
1846 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1847 #pragma omp parallel for schedule(dynamic,4) shared(status)
1849 for (y=0; y < (ssize_t) image->rows; y++)
1857 register PixelPacket
1860 if (status == MagickFalse)
1862 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1864 if (q == (PixelPacket *) NULL)
1869 for (x=(ssize_t) image->columns; x != 0; x--)
1871 q->red=logmap[ScaleQuantumToMap(q->red)];
1872 q->green=logmap[ScaleQuantumToMap(q->green)];
1873 q->blue=logmap[ScaleQuantumToMap(q->blue)];
1876 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1877 if (sync == MagickFalse)
1880 image_view=DestroyCacheView(image_view);
1881 logmap=(Quantum *) RelinquishMagickMemory(logmap);
1882 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1883 return(MagickFalse);
1890 Allocate the tables.
1892 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1894 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1896 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1898 if ((x_map == (TransformPacket *) NULL) ||
1899 (y_map == (TransformPacket *) NULL) ||
1900 (z_map == (TransformPacket *) NULL))
1902 if (z_map != (TransformPacket *) NULL)
1903 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1904 if (y_map != (TransformPacket *) NULL)
1905 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1906 if (x_map != (TransformPacket *) NULL)
1907 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1908 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1913 case OHTAColorspace:
1916 Initialize OHTA tables:
1918 R = I1+1.00000*I2-0.66668*I3
1919 G = I1+0.00000*I2+1.33333*I3
1920 B = I1-1.00000*I2-0.66668*I3
1922 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
1923 through QuantumRange.
1925 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1926 #pragma omp parallel for schedule(dynamic,4)
1928 for (i=0; i <= (ssize_t) MaxMap; i++)
1930 x_map[i].x=(MagickRealType) i;
1931 y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
1933 z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1935 x_map[i].y=(MagickRealType) i;
1936 y_map[i].y=0.000000f;
1937 z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
1939 x_map[i].z=(MagickRealType) i;
1940 y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1942 z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1947 case Rec601YCbCrColorspace:
1948 case YCbCrColorspace:
1951 Initialize YCbCr tables:
1954 G = Y-0.344136*Cb-0.714136*Cr
1957 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1958 through QuantumRange.
1960 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1961 #pragma omp parallel for schedule(dynamic,4)
1963 for (i=0; i <= (ssize_t) MaxMap; i++)
1965 x_map[i].x=(MagickRealType) i;
1966 y_map[i].x=0.000000f;
1967 z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
1968 (MagickRealType) MaxMap);
1969 x_map[i].y=(MagickRealType) i;
1970 y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
1971 (MagickRealType) MaxMap);
1972 z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
1973 (MagickRealType) MaxMap);
1974 x_map[i].z=(MagickRealType) i;
1975 y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
1976 (MagickRealType) MaxMap);
1977 z_map[i].z=0.000000f;
1981 case Rec709YCbCrColorspace:
1984 Initialize YCbCr tables:
1987 G = Y-0.187324*Cb-0.468124*Cr
1990 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1991 through QuantumRange.
1993 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1994 #pragma omp parallel for schedule(dynamic,4)
1996 for (i=0; i <= (ssize_t) MaxMap; i++)
1998 x_map[i].x=(MagickRealType) i;
1999 y_map[i].x=0.000000f;
2000 z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
2001 (MagickRealType) MaxMap);
2002 x_map[i].y=(MagickRealType) i;
2003 y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
2004 (MagickRealType) MaxMap);
2005 z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
2006 (MagickRealType) MaxMap);
2007 x_map[i].z=(MagickRealType) i;
2008 y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
2009 (MagickRealType) MaxMap);
2010 z_map[i].z=0.00000f;
2014 case sRGBColorspace:
2017 Nonlinear sRGB to linear RGB.
2019 R = 1.0*R+0.0*G+0.0*B
2020 G = 0.0*R+1.0*G+0.0*B
2021 B = 0.0*R+0.0*G+1.0*B
2023 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2024 #pragma omp parallel for schedule(dynamic,4)
2026 for (i=0; i <= (ssize_t) MaxMap; i++)
2028 x_map[i].x=1.0f*(MagickRealType) i;
2029 y_map[i].x=0.0f*(MagickRealType) i;
2030 z_map[i].x=0.0f*(MagickRealType) i;
2031 x_map[i].y=0.0f*(MagickRealType) i;
2032 y_map[i].y=1.0f*(MagickRealType) i;
2033 z_map[i].y=0.0f*(MagickRealType) i;
2034 x_map[i].z=0.0f*(MagickRealType) i;
2035 y_map[i].z=0.0f*(MagickRealType) i;
2036 z_map[i].z=1.0f*(MagickRealType) i;
2043 Initialize CIE XYZ tables (ITU R-709 RGB):
2045 R = 3.2404542*X-1.5371385*Y-0.4985314*Z
2046 G = -0.9692660*X+1.8760108*Y+0.0415560*Z
2047 B = 0.0556434*X-0.2040259*Y+1.057225*Z
2049 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2050 #pragma omp parallel for schedule(dynamic,4)
2052 for (i=0; i <= (ssize_t) MaxMap; i++)
2054 x_map[i].x=3.2404542f*(MagickRealType) i;
2055 x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2056 x_map[i].z=0.0556434f*(MagickRealType) i;
2057 y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2058 y_map[i].y=1.8760108f*(MagickRealType) i;
2059 y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2060 z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2061 z_map[i].y=0.0415560f*(MagickRealType) i;
2062 z_map[i].z=1.0572252f*(MagickRealType) i;
2069 Initialize YCC tables:
2072 G = Y-0.317038*C1-0.682243*C2
2075 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
2077 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2078 #pragma omp parallel for schedule(dynamic,4)
2080 for (i=0; i <= (ssize_t) MaxMap; i++)
2082 x_map[i].x=1.3584000f*(MagickRealType) i;
2083 y_map[i].x=0.0000000f;
2084 z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2085 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2086 x_map[i].y=1.3584000f*(MagickRealType) i;
2087 y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2088 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2089 z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2090 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2091 x_map[i].z=1.3584000f*(MagickRealType) i;
2092 y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2093 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2094 z_map[i].z=0.0000000f;
2101 Initialize YIQ tables:
2103 R = Y+0.95620*I+0.62140*Q
2104 G = Y-0.27270*I-0.64680*Q
2105 B = Y-1.10370*I+1.70060*Q
2107 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2108 through QuantumRange.
2110 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2111 #pragma omp parallel for schedule(dynamic,4)
2113 for (i=0; i <= (ssize_t) MaxMap; i++)
2115 x_map[i].x=(MagickRealType) i;
2116 y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2118 z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2120 x_map[i].y=(MagickRealType) i;
2121 y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2123 z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2125 x_map[i].z=(MagickRealType) i;
2126 y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2128 z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2133 case YPbPrColorspace:
2136 Initialize YPbPr tables:
2139 G = Y-0.344136*C1+0.714136*C2
2142 Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2143 through QuantumRange.
2145 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2146 #pragma omp parallel for schedule(dynamic,4)
2148 for (i=0; i <= (ssize_t) MaxMap; i++)
2150 x_map[i].x=(MagickRealType) i;
2151 y_map[i].x=0.000000f;
2152 z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2154 x_map[i].y=(MagickRealType) i;
2155 y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2157 z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2159 x_map[i].z=(MagickRealType) i;
2160 y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2162 z_map[i].z=0.00000f;
2170 Initialize YUV tables:
2173 G = Y-0.39380*U-0.58050*V
2176 U and V, normally -0.5 through 0.5, must be normalized to the range 0
2177 through QuantumRange.
2179 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2180 #pragma omp parallel for schedule(dynamic,4)
2182 for (i=0; i <= (ssize_t) MaxMap; i++)
2184 x_map[i].x=(MagickRealType) i;
2185 y_map[i].x=0.00000f;
2186 z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2188 x_map[i].y=(MagickRealType) i;
2189 y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2191 z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2193 x_map[i].z=(MagickRealType) i;
2194 y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2196 z_map[i].z=0.00000f;
2204 switch (image->storage_class)
2210 Convert DirectClass image.
2212 image_view=AcquireCacheView(image);
2213 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2214 #pragma omp parallel for schedule(dynamic,4) shared(status)
2216 for (y=0; y < (ssize_t) image->rows; y++)
2227 register PixelPacket
2230 if (status == MagickFalse)
2232 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2234 if (q == (PixelPacket *) NULL)
2239 for (x=0; x < (ssize_t) image->columns; x++)
2246 red=ScaleQuantumToMap(q->red);
2247 green=ScaleQuantumToMap(q->green);
2248 blue=ScaleQuantumToMap(q->blue);
2249 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2250 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2251 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2256 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2257 pixel.red=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2258 255.0*QuantumScale*pixel.red)]);
2259 pixel.green=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2260 255.0*QuantumScale*pixel.green)]);
2261 pixel.blue=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2262 255.0*QuantumScale*pixel.blue)]);
2266 case sRGBColorspace:
2268 if ((QuantumScale*pixel.red) <= 0.0031308)
2271 pixel.red=(MagickRealType) QuantumRange*(1.055*
2272 pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2273 if ((QuantumScale*pixel.green) <= 0.0031308)
2274 pixel.green*=12.92f;
2276 pixel.green=(MagickRealType) QuantumRange*(1.055*
2277 pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2278 if ((QuantumScale*pixel.blue) <= 0.0031308)
2281 pixel.blue=(MagickRealType) QuantumRange*(1.055*
2282 pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2288 q->red=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2290 q->green=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2292 q->blue=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2296 sync=SyncCacheViewAuthenticPixels(image_view,exception);
2297 if (sync == MagickFalse)
2299 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2304 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2305 #pragma omp critical (MagickCore_TransformRGBImage)
2307 proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
2309 if (proceed == MagickFalse)
2313 image_view=DestroyCacheView(image_view);
2319 Convert PseudoClass image.
2321 image_view=AcquireCacheView(image);
2322 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2323 #pragma omp parallel for schedule(dynamic,4) shared(status)
2325 for (i=0; i < (ssize_t) image->colors; i++)
2335 red=ScaleQuantumToMap(image->colormap[i].red);
2336 green=ScaleQuantumToMap(image->colormap[i].green);
2337 blue=ScaleQuantumToMap(image->colormap[i].blue);
2338 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2339 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2340 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2345 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2346 image->colormap[i].red=ScaleCharToQuantum(YCCMap[RoundToYCC(
2347 255.0*QuantumScale*pixel.red)]);
2348 image->colormap[i].green=ScaleCharToQuantum(YCCMap[RoundToYCC(
2349 255.0*QuantumScale*pixel.green)]);
2350 image->colormap[i].blue=ScaleCharToQuantum(YCCMap[RoundToYCC(
2351 255.0*QuantumScale*pixel.blue)]);
2355 case sRGBColorspace:
2357 if ((QuantumScale*pixel.red) <= 0.0031308)
2360 pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2361 pixel.red,(1.0/2.4))-0.055);
2362 if ((QuantumScale*pixel.green) <= 0.0031308)
2363 pixel.green*=12.92f;
2365 pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2366 pixel.green,(1.0/2.4))-0.055);
2367 if ((QuantumScale*pixel.blue) <= 0.0031308)
2370 pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2371 pixel.blue,(1.0/2.4))-0.055);
2375 image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
2376 QuantumScale*pixel.red);
2377 image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
2378 QuantumScale*pixel.green);
2379 image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
2380 QuantumScale*pixel.blue);
2385 image_view=DestroyCacheView(image_view);
2386 (void) SyncImage(image);
2391 Relinquish resources.
2393 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2394 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2395 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2396 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2397 return(MagickFalse);