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"
207 assert(image != (Image *) NULL);
208 assert(image->signature == MagickSignature);
209 if (image->debug != MagickFalse)
210 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
211 assert(colorspace != RGBColorspace);
212 assert(colorspace != TransparentColorspace);
213 assert(colorspace != UndefinedColorspace);
214 switch (image->colorspace)
217 case Rec601LumaColorspace:
218 case Rec709LumaColorspace:
220 case TransparentColorspace:
224 (void) TransformImageColorspace(image,image->colorspace);
228 if (SetImageColorspace(image,colorspace) == MagickFalse)
232 exception=(&image->exception);
238 Convert RGB to CMY colorspace.
240 if (image->storage_class == PseudoClass)
242 if (SyncImage(image) == MagickFalse)
244 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
247 image_view=AcquireCacheView(image);
248 #if defined(MAGICKCORE_OPENMP_SUPPORT)
249 #pragma omp parallel for schedule(dynamic,4) shared(status)
251 for (y=0; y < (long) image->rows; y++)
259 if (status == MagickFalse)
261 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
263 if (q == (PixelPacket *) NULL)
268 for (x=0; x < (long) image->columns; x++)
270 q->red=ClampToQuantum((MagickRealType) (QuantumRange-q->red));
271 q->green=ClampToQuantum((MagickRealType) (QuantumRange-q->green));
272 q->blue=ClampToQuantum((MagickRealType) (QuantumRange-q->blue));
275 sync=SyncCacheViewAuthenticPixels(image_view,exception);
276 if (sync == MagickFalse)
279 image_view=DestroyCacheView(image_view);
280 image->type=image->matte == MagickFalse ? ColorSeparationType :
281 ColorSeparationMatteType;
290 Convert RGB to CMYK colorspace.
292 if (image->storage_class == PseudoClass)
294 if (SyncImage(image) == MagickFalse)
296 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
299 GetMagickPixelPacket(image,&zero);
300 image_view=AcquireCacheView(image);
301 #if defined(MAGICKCORE_OPENMP_SUPPORT)
302 #pragma omp parallel for schedule(dynamic,4) shared(status)
304 for (y=0; y < (long) image->rows; y++)
318 if (status == MagickFalse)
320 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
322 if (q == (PixelPacket *) NULL)
327 indexes=GetCacheViewAuthenticIndexQueue(image_view);
329 for (x=0; x < (long) image->columns; x++)
331 SetMagickPixelPacket(image,q,indexes+x,&pixel);
332 ConvertRGBToCMYK(&pixel);
333 SetPixelPacket(image,&pixel,q,indexes+x);
336 sync=SyncCacheViewAuthenticPixels(image_view,exception);
337 if (sync == MagickFalse)
340 image_view=DestroyCacheView(image_view);
341 image->type=image->matte == MagickFalse ? ColorSeparationType :
342 ColorSeparationMatteType;
348 Transform image from RGB to HSB.
350 if (image->storage_class == PseudoClass)
352 if (SyncImage(image) == MagickFalse)
354 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
357 image_view=AcquireCacheView(image);
358 #if defined(MAGICKCORE_OPENMP_SUPPORT)
359 #pragma omp parallel for schedule(dynamic,4) shared(status)
361 for (y=0; y < (long) image->rows; y++)
374 if (status == MagickFalse)
376 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
378 if (q == (PixelPacket *) NULL)
386 for (x=0; x < (long) image->columns; x++)
388 ConvertRGBToHSB(q->red,q->green,q->blue,&hue,&saturation,&brightness);
389 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
390 q->green=ClampToQuantum((MagickRealType) QuantumRange*saturation);
391 q->blue=ClampToQuantum((MagickRealType) QuantumRange*brightness);
394 sync=SyncCacheViewAuthenticPixels(image_view,exception);
395 if (sync == MagickFalse)
398 image_view=DestroyCacheView(image_view);
404 Transform image from RGB to HSL.
406 if (image->storage_class == PseudoClass)
408 if (SyncImage(image) == MagickFalse)
410 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
413 image_view=AcquireCacheView(image);
414 #if defined(MAGICKCORE_OPENMP_SUPPORT)
415 #pragma omp parallel for schedule(dynamic,4) shared(status)
417 for (y=0; y < (long) image->rows; y++)
430 if (status == MagickFalse)
432 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
434 if (q == (PixelPacket *) NULL)
442 for (x=0; x < (long) image->columns; x++)
444 ConvertRGBToHSL(q->red,q->green,q->blue,&hue,&saturation,&lightness);
445 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
446 q->green=ClampToQuantum((MagickRealType) QuantumRange*saturation);
447 q->blue=ClampToQuantum((MagickRealType) QuantumRange*lightness);
450 sync=SyncCacheViewAuthenticPixels(image_view,exception);
451 if (sync == MagickFalse)
454 image_view=DestroyCacheView(image_view);
460 Transform image from RGB to HWB.
462 if (image->storage_class == PseudoClass)
464 if (SyncImage(image) == MagickFalse)
466 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
469 image_view=AcquireCacheView(image);
470 #if defined(MAGICKCORE_OPENMP_SUPPORT)
471 #pragma omp parallel for schedule(dynamic,4) shared(status)
473 for (y=0; y < (long) image->rows; y++)
486 if (status == MagickFalse)
488 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
490 if (q == (PixelPacket *) NULL)
498 for (x=0; x < (long) image->columns; x++)
500 ConvertRGBToHWB(q->red,q->green,q->blue,&hue,&whiteness,&blackness);
501 q->red=ClampToQuantum((MagickRealType) QuantumRange*hue);
502 q->green=ClampToQuantum((MagickRealType) QuantumRange*whiteness);
503 q->blue=ClampToQuantum((MagickRealType) QuantumRange*blackness);
506 sync=SyncCacheViewAuthenticPixels(image_view,exception);
507 if (sync == MagickFalse)
510 image_view=DestroyCacheView(image_view);
516 Transform image from RGB to Lab.
518 if (image->storage_class == PseudoClass)
520 if (SyncImage(image) == MagickFalse)
522 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
525 image_view=AcquireCacheView(image);
526 #if defined(MAGICKCORE_OPENMP_SUPPORT)
527 #pragma omp parallel for schedule(dynamic,4) shared(status)
529 for (y=0; y < (long) image->rows; y++)
545 if (status == MagickFalse)
547 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
549 if (q == (PixelPacket *) NULL)
560 for (x=0; x < (long) image->columns; x++)
562 ConvertRGBToXYZ(q->red,q->green,q->blue,&X,&Y,&Z);
563 ConvertXYZToLab(X,Y,Z,&L,&a,&b);
564 q->red=ClampToQuantum((MagickRealType) QuantumRange*L);
565 q->green=ClampToQuantum((MagickRealType) QuantumRange*a);
566 q->blue=ClampToQuantum((MagickRealType) QuantumRange*b);
569 sync=SyncCacheViewAuthenticPixels(image_view,exception);
570 if (sync == MagickFalse)
573 image_view=DestroyCacheView(image_view);
578 #define DisplayGamma (1.0/1.7)
579 #define FilmGamma 0.6
580 #define ReferenceBlack 95.0
581 #define ReferenceWhite 685.0
598 Transform RGB to Log colorspace.
600 density=DisplayGamma;
602 value=GetImageProperty(image,"gamma");
603 if (value != (const char *) NULL)
604 gamma=1.0/StringToDouble(value) != 0.0 ? StringToDouble(value) : 1.0;
605 film_gamma=FilmGamma;
606 value=GetImageProperty(image,"film-gamma");
607 if (value != (const char *) NULL)
608 film_gamma=StringToDouble(value);
609 reference_black=ReferenceBlack;
610 value=GetImageProperty(image,"reference-black");
611 if (value != (const char *) NULL)
612 reference_black=StringToDouble(value);
613 reference_white=ReferenceWhite;
614 value=GetImageProperty(image,"reference-white");
615 if (value != (const char *) NULL)
616 reference_white=StringToDouble(value);
617 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
619 if (logmap == (Quantum *) NULL)
620 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
622 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
624 #if defined(MAGICKCORE_OPENMP_SUPPORT)
625 #pragma omp parallel for schedule(dynamic,4)
627 for (i=0; i <= (long) MaxMap; i++)
628 logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
629 log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
630 0.002/film_gamma))/1024.0));
631 image_view=AcquireCacheView(image);
632 #if defined(MAGICKCORE_OPENMP_SUPPORT)
633 #pragma omp parallel for schedule(dynamic,4) shared(status)
635 for (y=0; y < (long) image->rows; y++)
643 if (status == MagickFalse)
645 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
647 if (q == (PixelPacket *) NULL)
652 for (x=(long) image->columns; x != 0; x--)
654 q->red=logmap[ScaleQuantumToMap(q->red)];
655 q->green=logmap[ScaleQuantumToMap(q->green)];
656 q->blue=logmap[ScaleQuantumToMap(q->blue)];
659 sync=SyncCacheViewAuthenticPixels(image_view,exception);
660 if (sync == MagickFalse)
663 image_view=DestroyCacheView(image_view);
664 logmap=(Quantum *) RelinquishMagickMemory(logmap);
673 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
675 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
677 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
679 if ((x_map == (TransformPacket *) NULL) ||
680 (y_map == (TransformPacket *) NULL) ||
681 (z_map == (TransformPacket *) NULL))
682 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
684 (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
690 Initialize OHTA tables:
692 I1 = 0.33333*R+0.33334*G+0.33333*B
693 I2 = 0.50000*R+0.00000*G-0.50000*B
694 I3 =-0.25000*R+0.50000*G-0.25000*B
696 I and Q, normally -0.5 through 0.5, are normalized to the range 0
697 through QuantumRange.
699 primary_info.y=(double) (MaxMap+1.0)/2.0;
700 primary_info.z=(double) (MaxMap+1.0)/2.0;
701 #if defined(MAGICKCORE_OPENMP_SUPPORT)
702 #pragma omp parallel for schedule(dynamic,4)
704 for (i=0; i <= (long) MaxMap; i++)
706 x_map[i].x=0.33333f*(MagickRealType) i;
707 y_map[i].x=0.33334f*(MagickRealType) i;
708 z_map[i].x=0.33333f*(MagickRealType) i;
709 x_map[i].y=0.50000f*(MagickRealType) i;
710 y_map[i].y=0.00000f*(MagickRealType) i;
711 z_map[i].y=(-0.50000f)*(MagickRealType) i;
712 x_map[i].z=(-0.25000f)*(MagickRealType) i;
713 y_map[i].z=0.50000f*(MagickRealType) i;
714 z_map[i].z=(-0.25000f)*(MagickRealType) i;
718 case Rec601LumaColorspace:
722 Initialize Rec601 luma tables:
724 G = 0.29900*R+0.58700*G+0.11400*B
726 #if defined(MAGICKCORE_OPENMP_SUPPORT)
727 #pragma omp parallel for schedule(dynamic,4)
729 for (i=0; i <= (long) MaxMap; i++)
731 x_map[i].x=0.29900f*(MagickRealType) i;
732 y_map[i].x=0.58700f*(MagickRealType) i;
733 z_map[i].x=0.11400f*(MagickRealType) i;
734 x_map[i].y=0.29900f*(MagickRealType) i;
735 y_map[i].y=0.58700f*(MagickRealType) i;
736 z_map[i].y=0.11400f*(MagickRealType) i;
737 x_map[i].z=0.29900f*(MagickRealType) i;
738 y_map[i].z=0.58700f*(MagickRealType) i;
739 z_map[i].z=0.11400f*(MagickRealType) i;
741 image->type=GrayscaleType;
744 case Rec601YCbCrColorspace:
745 case YCbCrColorspace:
748 Initialize YCbCr tables (ITU-R BT.601):
750 Y = 0.299000*R+0.587000*G+0.114000*B
751 Cb= -0.168736*R-0.331264*G+0.500000*B
752 Cr= 0.500000*R-0.418688*G-0.081312*B
754 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
755 through QuantumRange.
757 primary_info.y=(double) (MaxMap+1.0)/2.0;
758 primary_info.z=(double) (MaxMap+1.0)/2.0;
759 #if defined(MAGICKCORE_OPENMP_SUPPORT)
760 #pragma omp parallel for schedule(dynamic,4)
762 for (i=0; i <= (long) MaxMap; i++)
764 x_map[i].x=0.299000f*(MagickRealType) i;
765 y_map[i].x=0.587000f*(MagickRealType) i;
766 z_map[i].x=0.114000f*(MagickRealType) i;
767 x_map[i].y=(-0.168730f)*(MagickRealType) i;
768 y_map[i].y=(-0.331264f)*(MagickRealType) i;
769 z_map[i].y=0.500000f*(MagickRealType) i;
770 x_map[i].z=0.500000f*(MagickRealType) i;
771 y_map[i].z=(-0.418688f)*(MagickRealType) i;
772 z_map[i].z=(-0.081312f)*(MagickRealType) i;
776 case Rec709LumaColorspace:
779 Initialize Rec709 luma tables:
781 G = 0.21260*R+0.71520*G+0.07220*B
783 #if defined(MAGICKCORE_OPENMP_SUPPORT)
784 #pragma omp parallel for schedule(dynamic,4)
786 for (i=0; i <= (long) MaxMap; i++)
788 x_map[i].x=0.21260f*(MagickRealType) i;
789 y_map[i].x=0.71520f*(MagickRealType) i;
790 z_map[i].x=0.07220f*(MagickRealType) i;
791 x_map[i].y=0.21260f*(MagickRealType) i;
792 y_map[i].y=0.71520f*(MagickRealType) i;
793 z_map[i].y=0.07220f*(MagickRealType) i;
794 x_map[i].z=0.21260f*(MagickRealType) i;
795 y_map[i].z=0.71520f*(MagickRealType) i;
796 z_map[i].z=0.07220f*(MagickRealType) i;
800 case Rec709YCbCrColorspace:
803 Initialize YCbCr tables (ITU-R BT.709):
805 Y = 0.212600*R+0.715200*G+0.072200*B
806 Cb= -0.114572*R-0.385428*G+0.500000*B
807 Cr= 0.500000*R-0.454153*G-0.045847*B
809 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
810 through QuantumRange.
812 primary_info.y=(double) (MaxMap+1.0)/2.0;
813 primary_info.z=(double) (MaxMap+1.0)/2.0;
814 #if defined(MAGICKCORE_OPENMP_SUPPORT)
815 #pragma omp parallel for schedule(dynamic,4)
817 for (i=0; i <= (long) MaxMap; i++)
819 x_map[i].x=0.212600f*(MagickRealType) i;
820 y_map[i].x=0.715200f*(MagickRealType) i;
821 z_map[i].x=0.072200f*(MagickRealType) i;
822 x_map[i].y=(-0.114572f)*(MagickRealType) i;
823 y_map[i].y=(-0.385428f)*(MagickRealType) i;
824 z_map[i].y=0.500000f*(MagickRealType) i;
825 x_map[i].z=0.500000f*(MagickRealType) i;
826 y_map[i].z=(-0.454153f)*(MagickRealType) i;
827 z_map[i].z=(-0.045847f)*(MagickRealType) i;
834 Linear RGB to nonlinear sRGB (http://www.w3.org/Graphics/Color/sRGB):
836 R = 1.0*R+0.0*G+0.0*B
837 G = 0.0*R+0.1*G+0.0*B
838 B = 0.0*R+0.0*G+1.0*B
840 #if defined(MAGICKCORE_OPENMP_SUPPORT)
841 #pragma omp parallel for schedule(dynamic,4)
843 for (i=0; i <= (long) MaxMap; i++)
848 v=(MagickRealType) i/(MagickRealType) MaxMap;
849 if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.03928f)
852 v=(MagickRealType) MaxMap*pow((((double) i/MaxMap)+0.055)/1.055,2.4);
868 Initialize CIE XYZ tables (ITU-R 709 RGB):
870 X = 0.4124564*R+0.3575761*G+0.1804375*B
871 Y = 0.2126729*R+0.7151522*G+0.0721750*B
872 Z = 0.0193339*R+0.1191920*G+0.9503041*B
874 #if defined(MAGICKCORE_OPENMP_SUPPORT)
875 #pragma omp parallel for schedule(dynamic,4)
877 for (i=0; i <= (long) MaxMap; i++)
879 x_map[i].x=0.4124564f*(MagickRealType) i;
880 y_map[i].x=0.3575761f*(MagickRealType) i;
881 z_map[i].x=0.1804375f*(MagickRealType) i;
882 x_map[i].y=0.2126729f*(MagickRealType) i;
883 y_map[i].y=0.7151522f*(MagickRealType) i;
884 z_map[i].y=0.0721750f*(MagickRealType) i;
885 x_map[i].z=0.0193339f*(MagickRealType) i;
886 y_map[i].z=0.1191920f*(MagickRealType) i;
887 z_map[i].z=0.9503041f*(MagickRealType) i;
894 Initialize YCC tables:
896 Y = 0.29900*R+0.58700*G+0.11400*B
897 C1= -0.29900*R-0.58700*G+0.88600*B
898 C2= 0.70100*R-0.58700*G-0.11400*B
900 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
902 primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
903 primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
904 for (i=0; i <= (long) (0.018*MaxMap); i++)
906 x_map[i].x=0.003962014134275617f*(MagickRealType) i;
907 y_map[i].x=0.007778268551236748f*(MagickRealType) i;
908 z_map[i].x=0.001510600706713781f*(MagickRealType) i;
909 x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
910 y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
911 z_map[i].y=0.007190585689165425f*(MagickRealType) i;
912 x_map[i].z=0.006927257754597858f*(MagickRealType) i;
913 y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
914 z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
916 for ( ; i <= (long) MaxMap; i++)
918 x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
919 y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
920 z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
921 x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
922 y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
923 z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
924 x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
925 y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
926 z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
933 Initialize YIQ tables:
935 Y = 0.29900*R+0.58700*G+0.11400*B
936 I = 0.59600*R-0.27400*G-0.32200*B
937 Q = 0.21100*R-0.52300*G+0.31200*B
939 I and Q, normally -0.5 through 0.5, are normalized to the range 0
940 through QuantumRange.
942 primary_info.y=(double) (MaxMap+1.0)/2.0;
943 primary_info.z=(double) (MaxMap+1.0)/2.0;
944 #if defined(MAGICKCORE_OPENMP_SUPPORT)
945 #pragma omp parallel for schedule(dynamic,4)
947 for (i=0; i <= (long) MaxMap; i++)
949 x_map[i].x=0.29900f*(MagickRealType) i;
950 y_map[i].x=0.58700f*(MagickRealType) i;
951 z_map[i].x=0.11400f*(MagickRealType) i;
952 x_map[i].y=0.59600f*(MagickRealType) i;
953 y_map[i].y=(-0.27400f)*(MagickRealType) i;
954 z_map[i].y=(-0.32200f)*(MagickRealType) i;
955 x_map[i].z=0.21100f*(MagickRealType) i;
956 y_map[i].z=(-0.52300f)*(MagickRealType) i;
957 z_map[i].z=0.31200f*(MagickRealType) i;
961 case YPbPrColorspace:
964 Initialize YPbPr tables (ITU-R BT.601):
966 Y = 0.299000*R+0.587000*G+0.114000*B
967 Pb= -0.168736*R-0.331264*G+0.500000*B
968 Pr= 0.500000*R-0.418688*G-0.081312*B
970 Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
971 through QuantumRange.
973 primary_info.y=(double) (MaxMap+1.0)/2.0;
974 primary_info.z=(double) (MaxMap+1.0)/2.0;
975 #if defined(MAGICKCORE_OPENMP_SUPPORT)
976 #pragma omp parallel for schedule(dynamic,4)
978 for (i=0; i <= (long) MaxMap; i++)
980 x_map[i].x=0.299000f*(MagickRealType) i;
981 y_map[i].x=0.587000f*(MagickRealType) i;
982 z_map[i].x=0.114000f*(MagickRealType) i;
983 x_map[i].y=(-0.168736f)*(MagickRealType) i;
984 y_map[i].y=(-0.331264f)*(MagickRealType) i;
985 z_map[i].y=0.500000f*(MagickRealType) i;
986 x_map[i].z=0.500000f*(MagickRealType) i;
987 y_map[i].z=(-0.418688f)*(MagickRealType) i;
988 z_map[i].z=(-0.081312f)*(MagickRealType) i;
996 Initialize YUV tables:
998 Y = 0.29900*R+0.58700*G+0.11400*B
999 U = -0.14740*R-0.28950*G+0.43690*B
1000 V = 0.61500*R-0.51500*G-0.10000*B
1002 U and V, normally -0.5 through 0.5, are normalized to the range 0
1003 through QuantumRange. Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
1005 primary_info.y=(double) (MaxMap+1.0)/2.0;
1006 primary_info.z=(double) (MaxMap+1.0)/2.0;
1007 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1008 #pragma omp parallel for schedule(dynamic,4)
1010 for (i=0; i <= (long) MaxMap; i++)
1012 x_map[i].x=0.29900f*(MagickRealType) i;
1013 y_map[i].x=0.58700f*(MagickRealType) i;
1014 z_map[i].x=0.11400f*(MagickRealType) i;
1015 x_map[i].y=(-0.14740f)*(MagickRealType) i;
1016 y_map[i].y=(-0.28950f)*(MagickRealType) i;
1017 z_map[i].y=0.43690f*(MagickRealType) i;
1018 x_map[i].z=0.61500f*(MagickRealType) i;
1019 y_map[i].z=(-0.51500f)*(MagickRealType) i;
1020 z_map[i].z=(-0.10000f)*(MagickRealType) i;
1028 switch (image->storage_class)
1034 Convert DirectClass image.
1036 image_view=AcquireCacheView(image);
1037 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1038 #pragma omp parallel for schedule(dynamic,4) shared(status)
1040 for (y=0; y < (long) image->rows; y++)
1048 register PixelPacket
1051 register unsigned long
1056 if (status == MagickFalse)
1058 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1060 if (q == (PixelPacket *) NULL)
1065 for (x=0; x < (long) image->columns; x++)
1067 red=ScaleQuantumToMap(q->red);
1068 green=ScaleQuantumToMap(q->green);
1069 blue=ScaleQuantumToMap(q->blue);
1070 pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1071 (MagickRealType) primary_info.x;
1072 pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1073 (MagickRealType) primary_info.y;
1074 pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1075 (MagickRealType) primary_info.z;
1076 q->red=ScaleMapToQuantum(pixel.red);
1077 q->green=ScaleMapToQuantum(pixel.green);
1078 q->blue=ScaleMapToQuantum(pixel.blue);
1081 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1082 if (sync == MagickFalse)
1084 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1089 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1090 #pragma omp critical (MagickCore_RGBTransformImage)
1092 proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
1094 if (proceed == MagickFalse)
1098 image_view=DestroyCacheView(image_view);
1103 register unsigned long
1109 Convert PseudoClass image.
1111 image_view=AcquireCacheView(image);
1112 for (i=0; i < (long) image->colors; i++)
1117 red=ScaleQuantumToMap(image->colormap[i].red);
1118 green=ScaleQuantumToMap(image->colormap[i].green);
1119 blue=ScaleQuantumToMap(image->colormap[i].blue);
1120 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1121 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1122 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1123 image->colormap[i].red=ScaleMapToQuantum(pixel.red);
1124 image->colormap[i].green=ScaleMapToQuantum(pixel.green);
1125 image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
1127 image_view=DestroyCacheView(image_view);
1128 (void) SyncImage(image);
1133 Relinquish resources.
1135 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1136 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1137 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1138 if (SetImageColorspace(image,colorspace) == MagickFalse)
1139 return(MagickFalse);
1144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1148 % S e t I m a g e C o l o r s p a c e %
1152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154 % SetImageColorspace() sets the colorspace member of the Image structure.
1156 % The format of the SetImageColorspace method is:
1158 % MagickBooleanType SetImageColorspace(Image *image,
1159 % const ColorspaceType colorspace)
1161 % A description of each parameter follows:
1163 % o image: the image.
1165 % o colorspace: the colorspace.
1168 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1169 const ColorspaceType colorspace)
1174 if (image->colorspace == colorspace)
1176 image->colorspace=colorspace;
1177 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
1178 image->colorspace=colorspace; /* GRAY colorspace might get reset to RGB */
1179 return(cache == (Cache) NULL ? MagickFalse: MagickTrue);
1183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187 % T r a n s f o r m I m a g e C o l o r s p a c e %
1191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1193 % TransformImageColorspace() transforms an image colorspace.
1195 % The format of the TransformImageColorspace method is:
1197 % MagickBooleanType TransformImageColorspace(Image *image,
1198 % const ColorspaceType colorspace)
1200 % A description of each parameter follows:
1202 % o image: the image.
1204 % o colorspace: the colorspace.
1207 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1208 const ColorspaceType colorspace)
1213 assert(image != (Image *) NULL);
1214 assert(image->signature == MagickSignature);
1215 if (image->debug != MagickFalse)
1216 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1217 if (colorspace == UndefinedColorspace)
1219 if (SetImageColorspace(image,colorspace) == MagickFalse)
1220 return(MagickFalse);
1223 if (image->colorspace == colorspace)
1225 if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
1226 return(TransformRGBImage(image,image->colorspace));
1228 if ((image->colorspace != RGBColorspace) &&
1229 (image->colorspace != TransparentColorspace) &&
1230 (image->colorspace != GRAYColorspace))
1231 status=TransformRGBImage(image,image->colorspace);
1232 if (RGBTransformImage(image,colorspace) == MagickFalse)
1238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1242 + T r a n s f o r m R G B I m a g e %
1246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1248 % TransformRGBImage() converts the reference image from an alternate
1249 % colorspace to RGB. The transformation matrices are not the standard ones:
1250 % the weights are rescaled to normalize the range of the transformed values to
1251 % be [0..QuantumRange].
1253 % The format of the TransformRGBImage method is:
1255 % MagickBooleanType TransformRGBImage(Image *image,
1256 % const ColorspaceType colorspace)
1258 % A description of each parameter follows:
1260 % o image: the image.
1262 % o colorspace: the colorspace to transform the image to.
1266 static double LabF2(double alpha)
1271 if (alpha > (24.0/116.0))
1272 return(alpha*alpha*alpha);
1273 beta=(108.0/841.0)*(alpha-(16.0/116.0));
1279 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1280 double *X,double *Y,double *Z)
1288 assert(X != (double *) NULL);
1289 assert(Y != (double *) NULL);
1290 assert(Z != (double *) NULL);
1296 y=(100.0*L+16.0)/116.0;
1297 x=y+255.0*0.002*(a > 0.5 ? a-1.0 : a);
1298 z=y-255.0*0.005*(b > 0.5 ? b-1.0 : b);
1304 static inline unsigned short RoundToYCC(const MagickRealType value)
1310 return((unsigned short) (value+0.5));
1313 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1314 Quantum *red,Quantum *green,Quantum *blue)
1322 Convert XYZ to RGB colorspace.
1324 assert(red != (Quantum *) NULL);
1325 assert(green != (Quantum *) NULL);
1326 assert(blue != (Quantum *) NULL);
1327 r=3.2404542*x-1.5371385*y-0.4985314*z;
1328 g=(-0.9692660*x+1.8760108*y+0.0415560*z);
1329 b=0.0556434*x-0.2040259*y+1.0572252*z;
1331 r=1.055*pow(r,1.0/2.4)-0.055;
1335 g=1.055*pow(g,1.0/2.4)-0.055;
1339 b=1.055*pow(b,1.0/2.4)-0.055;
1342 *red=RoundToQuantum((MagickRealType) QuantumRange*r);
1343 *green=RoundToQuantum((MagickRealType) QuantumRange*g);
1344 *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
1347 static inline void ConvertCMYKToRGB(MagickPixelPacket *pixel)
1349 pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1350 (QuantumRange-pixel->index)+pixel->index);
1351 pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1352 (QuantumRange-pixel->index)+pixel->index);
1353 pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1354 (QuantumRange-pixel->index)+pixel->index);
1357 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1358 const ColorspaceType colorspace)
1360 #define D50X (0.9642)
1362 #define D50Z (0.8249)
1363 #define TransformRGBImageTag "Transform/Image"
1365 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1366 static const unsigned char
1367 YCCMap[351] = /* Photo CD information beyond 100% white, Gamma 2.2 */
1369 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1370 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
1371 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
1372 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58,
1373 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73,
1374 74, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89,
1375 90, 91, 92, 93, 94, 95, 97, 98, 99, 100, 101, 102, 103, 104,
1376 105, 106, 107, 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
1377 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134,
1378 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
1379 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
1380 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
1381 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
1382 190, 191, 192, 193, 193, 194, 195, 196, 197, 198, 199, 200, 201, 201,
1383 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
1384 214, 215, 215, 216, 217, 218, 218, 219, 220, 221, 221, 222, 223, 224,
1385 224, 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232, 233,
1386 234, 234, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241,
1387 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247,
1388 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
1389 251, 251, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253,
1390 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254,
1391 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255,
1392 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1393 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1419 assert(image != (Image *) NULL);
1420 assert(image->signature == MagickSignature);
1421 if (image->debug != MagickFalse)
1422 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1425 case GRAYColorspace:
1426 case Rec601LumaColorspace:
1427 case Rec709LumaColorspace:
1429 case TransparentColorspace:
1430 case UndefinedColorspace:
1437 exception=(&image->exception);
1443 Transform image from CMY to RGB.
1445 if (image->storage_class == PseudoClass)
1447 if (SyncImage(image) == MagickFalse)
1448 return(MagickFalse);
1449 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1450 return(MagickFalse);
1452 image_view=AcquireCacheView(image);
1453 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1454 #pragma omp parallel for schedule(dynamic,4) shared(status)
1456 for (y=0; y < (long) image->rows; y++)
1464 register PixelPacket
1467 if (status == MagickFalse)
1469 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1471 if (q == (PixelPacket *) NULL)
1476 for (x=0; x < (long) image->columns; x++)
1478 q->red=ClampToQuantum((MagickRealType) (QuantumRange-q->red));
1479 q->green=ClampToQuantum((MagickRealType) (QuantumRange-q->green));
1480 q->blue=ClampToQuantum((MagickRealType) (QuantumRange-q->blue));
1483 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1484 if (sync == MagickFalse)
1487 image_view=DestroyCacheView(image_view);
1488 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1489 return(MagickFalse);
1492 case CMYKColorspace:
1498 Transform image from CMYK to RGB.
1500 if (image->storage_class == PseudoClass)
1502 if (SyncImage(image) == MagickFalse)
1503 return(MagickFalse);
1504 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1505 return(MagickFalse);
1507 GetMagickPixelPacket(image,&zero);
1508 image_view=AcquireCacheView(image);
1509 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1510 #pragma omp parallel for schedule(dynamic,4) shared(status)
1512 for (y=0; y < (long) image->rows; y++)
1520 register IndexPacket
1526 register PixelPacket
1529 if (status == MagickFalse)
1531 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1533 if (q == (PixelPacket *) NULL)
1538 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1540 for (x=0; x < (long) image->columns; x++)
1542 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1543 ConvertCMYKToRGB(&pixel);
1544 SetPixelPacket(image,&pixel,q,indexes+x);
1547 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1548 if (sync == MagickFalse)
1551 image_view=DestroyCacheView(image_view);
1552 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1553 return(MagickFalse);
1559 Transform image from HSB to RGB.
1561 if (image->storage_class == PseudoClass)
1563 if (SyncImage(image) == MagickFalse)
1564 return(MagickFalse);
1565 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1566 return(MagickFalse);
1568 image_view=AcquireCacheView(image);
1569 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1570 #pragma omp parallel for schedule(dynamic,4) shared(status)
1572 for (y=0; y < (long) image->rows; y++)
1585 register PixelPacket
1588 if (status == MagickFalse)
1590 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1592 if (q == (PixelPacket *) NULL)
1597 for (x=0; x < (long) image->columns; x++)
1599 hue=(double) (QuantumScale*q->red);
1600 saturation=(double) (QuantumScale*q->green);
1601 brightness=(double) (QuantumScale*q->blue);
1602 ConvertHSBToRGB(hue,saturation,brightness,&q->red,&q->green,&q->blue);
1605 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1606 if (sync == MagickFalse)
1609 image_view=DestroyCacheView(image_view);
1610 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1611 return(MagickFalse);
1617 Transform image from HSL to RGB.
1619 if (image->storage_class == PseudoClass)
1621 if (SyncImage(image) == MagickFalse)
1622 return(MagickFalse);
1623 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1624 return(MagickFalse);
1626 image_view=AcquireCacheView(image);
1627 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1628 #pragma omp parallel for schedule(dynamic,4) shared(status)
1630 for (y=0; y < (long) image->rows; y++)
1643 register PixelPacket
1646 if (status == MagickFalse)
1648 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1650 if (q == (PixelPacket *) NULL)
1655 for (x=0; x < (long) image->columns; x++)
1657 hue=(double) (QuantumScale*q->red);
1658 saturation=(double) (QuantumScale*q->green);
1659 lightness=(double) (QuantumScale*q->blue);
1660 ConvertHSLToRGB(hue,saturation,lightness,&q->red,&q->green,&q->blue);
1663 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1664 if (sync == MagickFalse)
1667 image_view=DestroyCacheView(image_view);
1668 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1669 return(MagickFalse);
1675 Transform image from HWB to RGB.
1677 if (image->storage_class == PseudoClass)
1679 if (SyncImage(image) == MagickFalse)
1680 return(MagickFalse);
1681 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1682 return(MagickFalse);
1684 image_view=AcquireCacheView(image);
1685 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1686 #pragma omp parallel for schedule(dynamic,4) shared(status)
1688 for (y=0; y < (long) image->rows; y++)
1701 register PixelPacket
1704 if (status == MagickFalse)
1706 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1708 if (q == (PixelPacket *) NULL)
1713 for (x=0; x < (long) image->columns; x++)
1715 hue=(double) (QuantumScale*q->red);
1716 whiteness=(double) (QuantumScale*q->green);
1717 blackness=(double) (QuantumScale*q->blue);
1718 ConvertHWBToRGB(hue,whiteness,blackness,&q->red,&q->green,&q->blue);
1721 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1722 if (sync == MagickFalse)
1725 image_view=DestroyCacheView(image_view);
1726 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1727 return(MagickFalse);
1733 Transform image from Lab to RGB.
1735 if (image->storage_class == PseudoClass)
1737 if (SyncImage(image) == MagickFalse)
1738 return(MagickFalse);
1739 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1740 return(MagickFalse);
1742 image_view=AcquireCacheView(image);
1743 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1744 #pragma omp parallel for schedule(dynamic,4) shared(status)
1746 for (y=0; y < (long) image->rows; y++)
1762 register PixelPacket
1765 if (status == MagickFalse)
1767 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1769 if (q == (PixelPacket *) NULL)
1777 for (x=0; x < (long) image->columns; x++)
1779 L=QuantumScale*q->red;
1780 a=QuantumScale*q->green;
1781 b=QuantumScale*q->blue;
1782 ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
1783 ConvertXYZToRGB(X,Y,Z,&q->red,&q->green,&q->blue);
1786 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1787 if (sync == MagickFalse)
1790 image_view=DestroyCacheView(image_view);
1791 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1792 return(MagickFalse);
1812 Transform Log to RGB colorspace.
1814 density=DisplayGamma;
1816 value=GetImageProperty(image,"gamma");
1817 if (value != (const char *) NULL)
1818 gamma=1.0/StringToDouble(value) != 0.0 ? StringToDouble(value) : 1.0;
1819 film_gamma=FilmGamma;
1820 value=GetImageProperty(image,"film-gamma");
1821 if (value != (const char *) NULL)
1822 film_gamma=StringToDouble(value);
1823 reference_black=ReferenceBlack;
1824 value=GetImageProperty(image,"reference-black");
1825 if (value != (const char *) NULL)
1826 reference_black=StringToDouble(value);
1827 reference_white=ReferenceWhite;
1828 value=GetImageProperty(image,"reference-white");
1829 if (value != (const char *) NULL)
1830 reference_white=StringToDouble(value);
1831 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1833 if (logmap == (Quantum *) NULL)
1834 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1836 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
1838 for (i=0; i <= (long) (reference_black*MaxMap/1024.0); i++)
1839 logmap[i]=(Quantum) 0;
1840 for ( ; i < (long) (reference_white*MaxMap/1024.0); i++)
1841 logmap[i]=ClampToQuantum((MagickRealType) QuantumRange/(1.0-black)*
1842 (pow(10.0,(1024.0*i/MaxMap-reference_white)*
1843 (gamma/density)*0.002/film_gamma)-black));
1844 for ( ; i <= (long) MaxMap; i++)
1845 logmap[i]=(Quantum) QuantumRange;
1846 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1847 return(MagickFalse);
1848 image_view=AcquireCacheView(image);
1849 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1850 #pragma omp parallel for schedule(dynamic,4) shared(status)
1852 for (y=0; y < (long) image->rows; y++)
1860 register PixelPacket
1863 if (status == MagickFalse)
1865 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1867 if (q == (PixelPacket *) NULL)
1872 for (x=(long) image->columns; x != 0; x--)
1874 q->red=logmap[ScaleQuantumToMap(q->red)];
1875 q->green=logmap[ScaleQuantumToMap(q->green)];
1876 q->blue=logmap[ScaleQuantumToMap(q->blue)];
1879 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1880 if (sync == MagickFalse)
1883 image_view=DestroyCacheView(image_view);
1884 logmap=(Quantum *) RelinquishMagickMemory(logmap);
1885 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1886 return(MagickFalse);
1893 Allocate the tables.
1895 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1897 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1899 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1901 if ((x_map == (TransformPacket *) NULL) ||
1902 (y_map == (TransformPacket *) NULL) ||
1903 (z_map == (TransformPacket *) NULL))
1905 if (z_map != (TransformPacket *) NULL)
1906 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1907 if (y_map != (TransformPacket *) NULL)
1908 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1909 if (x_map != (TransformPacket *) NULL)
1910 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1911 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1916 case OHTAColorspace:
1919 Initialize OHTA tables:
1921 R = I1+1.00000*I2-0.66668*I3
1922 G = I1+0.00000*I2+1.33333*I3
1923 B = I1-1.00000*I2-0.66668*I3
1925 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
1926 through QuantumRange.
1928 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1929 #pragma omp parallel for schedule(dynamic,4)
1931 for (i=0; i <= (long) MaxMap; i++)
1933 x_map[i].x=(MagickRealType) i;
1934 y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
1936 z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1938 x_map[i].y=(MagickRealType) i;
1939 y_map[i].y=0.000000f;
1940 z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
1942 x_map[i].z=(MagickRealType) i;
1943 y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1945 z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1950 case Rec601YCbCrColorspace:
1951 case YCbCrColorspace:
1954 Initialize YCbCr tables:
1957 G = Y-0.344136*Cb-0.714136*Cr
1960 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1961 through QuantumRange.
1963 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1964 #pragma omp parallel for schedule(dynamic,4)
1966 for (i=0; i <= (long) MaxMap; i++)
1968 x_map[i].x=(MagickRealType) i;
1969 y_map[i].x=0.000000f;
1970 z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
1971 (MagickRealType) MaxMap);
1972 x_map[i].y=(MagickRealType) i;
1973 y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
1974 (MagickRealType) MaxMap);
1975 z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
1976 (MagickRealType) MaxMap);
1977 x_map[i].z=(MagickRealType) i;
1978 y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
1979 (MagickRealType) MaxMap);
1980 z_map[i].z=0.000000f;
1984 case Rec709YCbCrColorspace:
1987 Initialize YCbCr tables:
1990 G = Y-0.187324*Cb-0.468124*Cr
1993 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1994 through QuantumRange.
1996 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1997 #pragma omp parallel for schedule(dynamic,4)
1999 for (i=0; i <= (long) MaxMap; i++)
2001 x_map[i].x=(MagickRealType) i;
2002 y_map[i].x=0.000000f;
2003 z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
2004 (MagickRealType) MaxMap);
2005 x_map[i].y=(MagickRealType) i;
2006 y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
2007 (MagickRealType) MaxMap);
2008 z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
2009 (MagickRealType) MaxMap);
2010 x_map[i].z=(MagickRealType) i;
2011 y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
2012 (MagickRealType) MaxMap);
2013 z_map[i].z=0.00000f;
2017 case sRGBColorspace:
2020 Nonlinear sRGB to linear RGB.
2022 R = 1.0*R+0.0*G+0.0*B
2023 G = 0.0*R+1.0*G+0.0*B
2024 B = 0.0*R+0.0*G+1.0*B
2026 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2027 #pragma omp parallel for schedule(dynamic,4)
2029 for (i=0; i <= (long) MaxMap; i++)
2031 x_map[i].x=1.0f*(MagickRealType) i;
2032 y_map[i].x=0.0f*(MagickRealType) i;
2033 z_map[i].x=0.0f*(MagickRealType) i;
2034 x_map[i].y=0.0f*(MagickRealType) i;
2035 y_map[i].y=1.0f*(MagickRealType) i;
2036 z_map[i].y=0.0f*(MagickRealType) i;
2037 x_map[i].z=0.0f*(MagickRealType) i;
2038 y_map[i].z=0.0f*(MagickRealType) i;
2039 z_map[i].z=1.0f*(MagickRealType) i;
2046 Initialize CIE XYZ tables (ITU R-709 RGB):
2048 R = 3.2404542*X-1.5371385*Y-0.4985314*Z
2049 G = -0.9692660*X+1.8760108*Y+0.0415560*Z
2050 B = 0.0556434*X-0.2040259*Y+1.057225*Z
2052 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2053 #pragma omp parallel for schedule(dynamic,4)
2055 for (i=0; i <= (long) MaxMap; i++)
2057 x_map[i].x=3.2404542f*(MagickRealType) i;
2058 x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2059 x_map[i].z=0.0556434f*(MagickRealType) i;
2060 y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2061 y_map[i].y=1.8760108f*(MagickRealType) i;
2062 y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2063 z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2064 z_map[i].y=0.0415560f*(MagickRealType) i;
2065 z_map[i].z=1.0572252f*(MagickRealType) i;
2072 Initialize YCC tables:
2075 G = Y-0.317038*C1-0.682243*C2
2078 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
2080 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2081 #pragma omp parallel for schedule(dynamic,4)
2083 for (i=0; i <= (long) MaxMap; i++)
2085 x_map[i].x=1.3584000f*(MagickRealType) i;
2086 y_map[i].x=0.0000000f;
2087 z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2088 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2089 x_map[i].y=1.3584000f*(MagickRealType) i;
2090 y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2091 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2092 z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2093 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2094 x_map[i].z=1.3584000f*(MagickRealType) i;
2095 y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2096 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2097 z_map[i].z=0.0000000f;
2104 Initialize YIQ tables:
2106 R = Y+0.95620*I+0.62140*Q
2107 G = Y-0.27270*I-0.64680*Q
2108 B = Y-1.10370*I+1.70060*Q
2110 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2111 through QuantumRange.
2113 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2114 #pragma omp parallel for schedule(dynamic,4)
2116 for (i=0; i <= (long) MaxMap; i++)
2118 x_map[i].x=(MagickRealType) i;
2119 y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2121 z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2123 x_map[i].y=(MagickRealType) i;
2124 y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2126 z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2128 x_map[i].z=(MagickRealType) i;
2129 y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2131 z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2136 case YPbPrColorspace:
2139 Initialize YPbPr tables:
2142 G = Y-0.344136*C1+0.714136*C2
2145 Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2146 through QuantumRange.
2148 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2149 #pragma omp parallel for schedule(dynamic,4)
2151 for (i=0; i <= (long) MaxMap; i++)
2153 x_map[i].x=(MagickRealType) i;
2154 y_map[i].x=0.000000f;
2155 z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2157 x_map[i].y=(MagickRealType) i;
2158 y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2160 z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2162 x_map[i].z=(MagickRealType) i;
2163 y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2165 z_map[i].z=0.00000f;
2173 Initialize YUV tables:
2176 G = Y-0.39380*U-0.58050*V
2179 U and V, normally -0.5 through 0.5, must be normalized to the range 0
2180 through QuantumRange.
2182 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2183 #pragma omp parallel for schedule(dynamic,4)
2185 for (i=0; i <= (long) MaxMap; i++)
2187 x_map[i].x=(MagickRealType) i;
2188 y_map[i].x=0.00000f;
2189 z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2191 x_map[i].y=(MagickRealType) i;
2192 y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2194 z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2196 x_map[i].z=(MagickRealType) i;
2197 y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2199 z_map[i].z=0.00000f;
2207 switch (image->storage_class)
2213 Convert DirectClass image.
2215 image_view=AcquireCacheView(image);
2216 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2217 #pragma omp parallel for schedule(dynamic,4) shared(status)
2219 for (y=0; y < (long) image->rows; y++)
2230 register PixelPacket
2233 if (status == MagickFalse)
2235 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2237 if (q == (PixelPacket *) NULL)
2242 for (x=0; x < (long) image->columns; x++)
2244 register unsigned long
2249 red=ScaleQuantumToMap(q->red);
2250 green=ScaleQuantumToMap(q->green);
2251 blue=ScaleQuantumToMap(q->blue);
2252 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2253 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2254 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2259 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2260 pixel.red=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2261 255.0*QuantumScale*pixel.red)]);
2262 pixel.green=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2263 255.0*QuantumScale*pixel.green)]);
2264 pixel.blue=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2265 255.0*QuantumScale*pixel.blue)]);
2269 case sRGBColorspace:
2271 if ((QuantumScale*pixel.red) <= 0.0031308)
2274 pixel.red=(MagickRealType) QuantumRange*(1.055*
2275 pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2276 if ((QuantumScale*pixel.green) <= 0.0031308)
2277 pixel.green*=12.92f;
2279 pixel.green=(MagickRealType) QuantumRange*(1.055*
2280 pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2281 if ((QuantumScale*pixel.blue) <= 0.0031308)
2284 pixel.blue=(MagickRealType) QuantumRange*(1.055*
2285 pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2291 q->red=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2293 q->green=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2295 q->blue=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2299 sync=SyncCacheViewAuthenticPixels(image_view,exception);
2300 if (sync == MagickFalse)
2302 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2307 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2308 #pragma omp critical (MagickCore_TransformRGBImage)
2310 proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
2312 if (proceed == MagickFalse)
2316 image_view=DestroyCacheView(image_view);
2322 Convert PseudoClass image.
2324 image_view=AcquireCacheView(image);
2325 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2326 #pragma omp parallel for schedule(dynamic,4) shared(status)
2328 for (i=0; i < (long) image->colors; i++)
2333 register unsigned long
2338 red=ScaleQuantumToMap(image->colormap[i].red);
2339 green=ScaleQuantumToMap(image->colormap[i].green);
2340 blue=ScaleQuantumToMap(image->colormap[i].blue);
2341 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2342 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2343 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2348 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2349 image->colormap[i].red=ScaleCharToQuantum(YCCMap[RoundToYCC(
2350 255.0*QuantumScale*pixel.red)]);
2351 image->colormap[i].green=ScaleCharToQuantum(YCCMap[RoundToYCC(
2352 255.0*QuantumScale*pixel.green)]);
2353 image->colormap[i].blue=ScaleCharToQuantum(YCCMap[RoundToYCC(
2354 255.0*QuantumScale*pixel.blue)]);
2358 case sRGBColorspace:
2360 if ((QuantumScale*pixel.red) <= 0.0031308)
2363 pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2364 pixel.red,(1.0/2.4))-0.055);
2365 if ((QuantumScale*pixel.green) <= 0.0031308)
2366 pixel.green*=12.92f;
2368 pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2369 pixel.green,(1.0/2.4))-0.055);
2370 if ((QuantumScale*pixel.blue) <= 0.0031308)
2373 pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2374 pixel.blue,(1.0/2.4))-0.055);
2378 image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
2379 QuantumScale*pixel.red);
2380 image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
2381 QuantumScale*pixel.green);
2382 image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
2383 QuantumScale*pixel.blue);
2388 image_view=DestroyCacheView(image_view);
2389 (void) SyncImage(image);
2394 Relinquish resources.
2396 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2397 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2398 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2399 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2400 return(MagickFalse);