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-2009 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/utility.h"
68 typedef struct _TransformPacket
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 + R G B T r a n s f o r m I m a g e %
85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 % RGBTransformImage() converts the reference image from RGB to an alternate
88 % colorspace. The transformation matrices are not the standard ones: the
89 % weights are rescaled to normalized the range of the transformed values to
90 % be [0..QuantumRange].
92 % The format of the RGBTransformImage method is:
94 % MagickBooleanType RGBTransformImage(Image *image,
95 % const ColorspaceType colorspace)
97 % A description of each parameter follows:
101 % o colorspace: the colorspace to transform the image to.
105 static inline void ConvertRGBToXYZ(const Quantum red,const Quantum green,
106 const Quantum blue,double *X,double *Y,double *Z)
113 assert(X != (double *) NULL);
114 assert(Y != (double *) NULL);
115 assert(Z != (double *) NULL);
117 g=QuantumScale*green;
119 *X=0.4124240*r+0.3575790*g+0.1804640*b;
120 *Y=0.2126560*r+0.7151580*g+0.0721856*b;
121 *Z=0.0193324*r+0.1191930*g+0.9504440*b;
124 static inline void ConvertXYZToLab(const double X,const double Y,const double Z,
125 double *L,double *a,double *b)
132 assert(L != (double *) NULL);
133 assert(a != (double *) NULL);
134 assert(b != (double *) NULL);
136 if (x > (216/24389.0))
139 x=(7.787*x)+(16.0/116.0);
141 if (y > (216/24389.0))
144 y=(7.787*y)+(16.0/116.0);
146 if (z > (216/24389.0))
149 z=(7.787*z)+(16.0/116.0);
150 *L=0.5*((1.160*y)-0.160+1.0);
151 *a=0.5*(5.000*(x-y)+1.0);
152 *b=0.5*(2.000*(y-z)+1.0);
155 MagickExport MagickBooleanType RGBTransformImage(Image *image,
156 const ColorspaceType colorspace)
158 #define RGBTransformImageTag "RGBTransform/Image"
185 assert(image != (Image *) NULL);
186 assert(image->signature == MagickSignature);
187 if (image->debug != MagickFalse)
188 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
189 assert(colorspace != RGBColorspace);
190 assert(colorspace != TransparentColorspace);
191 assert(colorspace != UndefinedColorspace);
192 switch (image->colorspace)
195 case Rec601LumaColorspace:
196 case Rec709LumaColorspace:
198 case TransparentColorspace:
202 (void) TransformImageColorspace(image,image->colorspace);
206 if (SetImageColorspace(image,colorspace) == MagickFalse)
210 exception=(&image->exception);
216 Convert RGB to CMY colorspace.
218 if (image->storage_class == PseudoClass)
220 if (SyncImage(image) == MagickFalse)
222 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
225 image_view=AcquireCacheView(image);
226 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
227 #pragma omp parallel for shared(status)
229 for (y=0; y < (long) image->rows; y++)
237 if (status == MagickFalse)
239 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
241 if (q == (PixelPacket *) NULL)
246 for (x=0; x < (long) image->columns; x++)
248 q->red=RoundToQuantum((MagickRealType) (QuantumRange-q->red));
249 q->green=RoundToQuantum((MagickRealType) (QuantumRange-q->green));
250 q->blue=RoundToQuantum((MagickRealType) (QuantumRange-q->blue));
253 sync=SyncCacheViewAuthenticPixels(image_view,exception);
254 if (sync == MagickFalse)
257 image_view=DestroyCacheView(image_view);
258 image->type=image->matte == MagickFalse ? ColorSeparationType :
259 ColorSeparationMatteType;
268 Convert RGB to CMYK colorspace.
270 if (image->storage_class == PseudoClass)
272 if (SyncImage(image) == MagickFalse)
274 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
277 GetMagickPixelPacket(image,&zero);
278 image_view=AcquireCacheView(image);
279 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
280 #pragma omp parallel for shared(status)
282 for (y=0; y < (long) image->rows; y++)
296 if (status == MagickFalse)
298 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
300 if (q == (PixelPacket *) NULL)
305 indexes=GetCacheViewAuthenticIndexQueue(image_view);
307 for (x=0; x < (long) image->columns; x++)
309 SetMagickPixelPacket(image,q,indexes+x,&pixel);
310 ConvertRGBToCMYK(&pixel);
311 SetPixelPacket(image,&pixel,q,indexes+x);
314 sync=SyncCacheViewAuthenticPixels(image_view,exception);
315 if (sync == MagickFalse)
318 image_view=DestroyCacheView(image_view);
319 image->type=image->matte == MagickFalse ? ColorSeparationType :
320 ColorSeparationMatteType;
326 Transform image from RGB to HSB.
328 if (image->storage_class == PseudoClass)
330 if (SyncImage(image) == MagickFalse)
332 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
335 image_view=AcquireCacheView(image);
336 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
337 #pragma omp parallel for shared(status)
339 for (y=0; y < (long) image->rows; y++)
352 if (status == MagickFalse)
354 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
356 if (q == (PixelPacket *) NULL)
364 for (x=0; x < (long) image->columns; x++)
366 ConvertRGBToHSB(q->red,q->green,q->blue,&hue,&saturation,&brightness);
367 q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
368 q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
369 q->blue=RoundToQuantum((MagickRealType) QuantumRange*brightness);
372 sync=SyncCacheViewAuthenticPixels(image_view,exception);
373 if (sync == MagickFalse)
376 image_view=DestroyCacheView(image_view);
382 Transform image from RGB to HSL.
384 if (image->storage_class == PseudoClass)
386 if (SyncImage(image) == MagickFalse)
388 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
391 image_view=AcquireCacheView(image);
392 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
393 #pragma omp parallel for shared(status)
395 for (y=0; y < (long) image->rows; y++)
408 if (status == MagickFalse)
410 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
412 if (q == (PixelPacket *) NULL)
420 for (x=0; x < (long) image->columns; x++)
422 ConvertRGBToHSL(q->red,q->green,q->blue,&hue,&saturation,&lightness);
423 q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
424 q->green=RoundToQuantum((MagickRealType) QuantumRange*saturation);
425 q->blue=RoundToQuantum((MagickRealType) QuantumRange*lightness);
428 sync=SyncCacheViewAuthenticPixels(image_view,exception);
429 if (sync == MagickFalse)
432 image_view=DestroyCacheView(image_view);
438 Transform image from RGB to HWB.
440 if (image->storage_class == PseudoClass)
442 if (SyncImage(image) == MagickFalse)
444 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
447 image_view=AcquireCacheView(image);
448 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
449 #pragma omp parallel for shared(status)
451 for (y=0; y < (long) image->rows; y++)
464 if (status == MagickFalse)
466 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
468 if (q == (PixelPacket *) NULL)
476 for (x=0; x < (long) image->columns; x++)
478 ConvertRGBToHWB(q->red,q->green,q->blue,&hue,&whiteness,&blackness);
479 q->red=RoundToQuantum((MagickRealType) QuantumRange*hue);
480 q->green=RoundToQuantum((MagickRealType) QuantumRange*whiteness);
481 q->blue=RoundToQuantum((MagickRealType) QuantumRange*blackness);
484 sync=SyncCacheViewAuthenticPixels(image_view,exception);
485 if (sync == MagickFalse)
488 image_view=DestroyCacheView(image_view);
494 Transform image from RGB to Lab.
496 if (image->storage_class == PseudoClass)
498 if (SyncImage(image) == MagickFalse)
500 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
503 image_view=AcquireCacheView(image);
504 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
505 #pragma omp parallel for shared(status)
507 for (y=0; y < (long) image->rows; y++)
523 if (status == MagickFalse)
525 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
527 if (q == (PixelPacket *) NULL)
538 for (x=0; x < (long) image->columns; x++)
540 ConvertRGBToXYZ(q->red,q->green,q->blue,&X,&Y,&Z);
541 ConvertXYZToLab(X,Y,Z,&L,&a,&b);
542 q->red=RoundToQuantum((MagickRealType) QuantumRange*L);
543 q->green=RoundToQuantum((MagickRealType) QuantumRange*a);
544 q->blue=RoundToQuantum((MagickRealType) QuantumRange*b);
547 sync=SyncCacheViewAuthenticPixels(image_view,exception);
548 if (sync == MagickFalse)
551 image_view=DestroyCacheView(image_view);
556 #define ReferenceBlack 95.0
557 #define ReferenceWhite 685.0
558 #define DisplayGamma (1.0/1.7)
574 Transform RGB to Log colorspace.
578 value=GetImageProperty(image,"gamma");
579 if (value != (const char *) NULL)
580 gamma=1.0/atof(value) != 0.0 ? atof(value) : 1.0;
581 reference_black=ReferenceBlack;
582 value=GetImageProperty(image,"reference-black");
583 if (value != (const char *) NULL)
584 reference_black=atof(value);
585 reference_white=ReferenceWhite;
586 value=GetImageProperty(image,"reference-white");
587 if (value != (const char *) NULL)
588 reference_white=atof(value);
589 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
591 if (logmap == (Quantum *) NULL)
592 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
594 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
596 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
597 #pragma omp parallel for
599 for (i=0; i <= (long) MaxMap; i++)
600 logmap[i]=ScaleMapToQuantum((MagickRealType) (MaxMap*(reference_white+
601 log10(black+((MagickRealType) i/MaxMap)*(1.0-black))/((gamma/density)*
602 0.002/0.6))/1024.0+0.5));
603 image_view=AcquireCacheView(image);
604 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
605 #pragma omp parallel for shared(status)
607 for (y=0; y < (long) image->rows; y++)
615 if (status == MagickFalse)
617 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
619 if (q == (PixelPacket *) NULL)
624 for (x=(long) image->columns; x != 0; x--)
626 q->red=logmap[ScaleQuantumToMap(q->red)];
627 q->green=logmap[ScaleQuantumToMap(q->green)];
628 q->blue=logmap[ScaleQuantumToMap(q->blue)];
631 sync=SyncCacheViewAuthenticPixels(image_view,exception);
632 if (sync == MagickFalse)
635 image_view=DestroyCacheView(image_view);
636 logmap=(Quantum *) RelinquishMagickMemory(logmap);
645 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
647 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
649 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
651 if ((x_map == (TransformPacket *) NULL) ||
652 (y_map == (TransformPacket *) NULL) ||
653 (z_map == (TransformPacket *) NULL))
654 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
656 (void) ResetMagickMemory(&primary_info,0,sizeof(primary_info));
662 Initialize OHTA tables:
664 I1 = 0.33333*R+0.33334*G+0.33333*B
665 I2 = 0.50000*R+0.00000*G-0.50000*B
666 I3 =-0.25000*R+0.50000*G-0.25000*B
668 I and Q, normally -0.5 through 0.5, are normalized to the range 0
669 through QuantumRange.
671 primary_info.y=(double) (MaxMap+1.0)/2.0;
672 primary_info.z=(double) (MaxMap+1.0)/2.0;
673 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
674 #pragma omp parallel for
676 for (i=0; i <= (long) MaxMap; i++)
678 x_map[i].x=0.33333f*(MagickRealType) i;
679 y_map[i].x=0.33334f*(MagickRealType) i;
680 z_map[i].x=0.33333f*(MagickRealType) i;
681 x_map[i].y=0.50000f*(MagickRealType) i;
682 y_map[i].y=0.00000f*(MagickRealType) i;
683 z_map[i].y=(-0.50000f)*(MagickRealType) i;
684 x_map[i].z=(-0.25000f)*(MagickRealType) i;
685 y_map[i].z=0.50000f*(MagickRealType) i;
686 z_map[i].z=(-0.25000f)*(MagickRealType) i;
690 case Rec601LumaColorspace:
694 Initialize Rec601 luma tables:
696 G = 0.29900*R+0.58700*G+0.11400*B
698 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
699 #pragma omp parallel for
701 for (i=0; i <= (long) MaxMap; i++)
703 x_map[i].x=0.29900f*(MagickRealType) i;
704 y_map[i].x=0.58700f*(MagickRealType) i;
705 z_map[i].x=0.11400f*(MagickRealType) i;
706 x_map[i].y=0.29900f*(MagickRealType) i;
707 y_map[i].y=0.58700f*(MagickRealType) i;
708 z_map[i].y=0.11400f*(MagickRealType) i;
709 x_map[i].z=0.29900f*(MagickRealType) i;
710 y_map[i].z=0.58700f*(MagickRealType) i;
711 z_map[i].z=0.11400f*(MagickRealType) i;
713 image->type=GrayscaleType;
716 case Rec601YCbCrColorspace:
717 case YCbCrColorspace:
720 Initialize YCbCr tables (ITU-R BT.601):
722 Y = 0.299000*R+0.587000*G+0.114000*B
723 Cb= -0.168736*R-0.331264*G+0.500000*B
724 Cr= 0.500000*R-0.418688*G-0.081312*B
726 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
727 through QuantumRange.
729 primary_info.y=(double) (MaxMap+1.0)/2.0;
730 primary_info.z=(double) (MaxMap+1.0)/2.0;
731 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
732 #pragma omp parallel for
734 for (i=0; i <= (long) MaxMap; i++)
736 x_map[i].x=0.299000f*(MagickRealType) i;
737 y_map[i].x=0.587000f*(MagickRealType) i;
738 z_map[i].x=0.114000f*(MagickRealType) i;
739 x_map[i].y=(-0.168730f)*(MagickRealType) i;
740 y_map[i].y=(-0.331264f)*(MagickRealType) i;
741 z_map[i].y=0.500000f*(MagickRealType) i;
742 x_map[i].z=0.500000f*(MagickRealType) i;
743 y_map[i].z=(-0.418688f)*(MagickRealType) i;
744 z_map[i].z=(-0.081312f)*(MagickRealType) i;
748 case Rec709LumaColorspace:
751 Initialize Rec709 luma tables:
753 G = 0.21260*R+0.71520*G+0.07220*B
755 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
756 #pragma omp parallel for
758 for (i=0; i <= (long) MaxMap; i++)
760 x_map[i].x=0.21260f*(MagickRealType) i;
761 y_map[i].x=0.71520f*(MagickRealType) i;
762 z_map[i].x=0.07220f*(MagickRealType) i;
763 x_map[i].y=0.21260f*(MagickRealType) i;
764 y_map[i].y=0.71520f*(MagickRealType) i;
765 z_map[i].y=0.07220f*(MagickRealType) i;
766 x_map[i].z=0.21260f*(MagickRealType) i;
767 y_map[i].z=0.71520f*(MagickRealType) i;
768 z_map[i].z=0.07220f*(MagickRealType) i;
772 case Rec709YCbCrColorspace:
775 Initialize YCbCr tables (ITU-R BT.709):
777 Y = 0.212600*R+0.715200*G+0.072200*B
778 Cb= -0.114572*R-0.385428*G+0.500000*B
779 Cr= 0.500000*R-0.454153*G-0.045847*B
781 Cb and Cr, normally -0.5 through 0.5, are normalized to the range 0
782 through QuantumRange.
784 primary_info.y=(double) (MaxMap+1.0)/2.0;
785 primary_info.z=(double) (MaxMap+1.0)/2.0;
786 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
787 #pragma omp parallel for
789 for (i=0; i <= (long) MaxMap; i++)
791 x_map[i].x=0.212600f*(MagickRealType) i;
792 y_map[i].x=0.715200f*(MagickRealType) i;
793 z_map[i].x=0.072200f*(MagickRealType) i;
794 x_map[i].y=(-0.114572f)*(MagickRealType) i;
795 y_map[i].y=(-0.385428f)*(MagickRealType) i;
796 z_map[i].y=0.500000f*(MagickRealType) i;
797 x_map[i].z=0.500000f*(MagickRealType) i;
798 y_map[i].z=(-0.454153f)*(MagickRealType) i;
799 z_map[i].z=(-0.045847f)*(MagickRealType) i;
806 Linear RGB to nonlinear sRGB (http://www.w3.org/Graphics/Color/sRGB):
808 R = 1.0*R+0.0*G+0.0*B
809 G = 0.0*R+0.1*G+0.0*B
810 B = 0.0*R+0.0*G+1.0*B
812 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
813 #pragma omp parallel for
815 for (i=0; i <= (long) MaxMap; i++)
820 v=(MagickRealType) i/(MagickRealType) MaxMap;
821 if (((MagickRealType) i/(MagickRealType) MaxMap) <= 0.03928f)
824 v=(MagickRealType) MaxMap*pow((((double) i/MaxMap)+0.055)/1.055,2.4);
840 Initialize CIE XYZ tables (ITU-R 709 RGB):
842 X = 0.4124564*R+0.3575761*G+0.1804375*B
843 Y = 0.2126729*R+0.7151522*G+0.0721750*B
844 Z = 0.0193339*R+0.1191920*G+0.9503041*B
846 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
847 #pragma omp parallel for
849 for (i=0; i <= (long) MaxMap; i++)
851 x_map[i].x=0.4124564f*(MagickRealType) i;
852 y_map[i].x=0.3575761f*(MagickRealType) i;
853 z_map[i].x=0.1804375f*(MagickRealType) i;
854 x_map[i].y=0.2126729f*(MagickRealType) i;
855 y_map[i].y=0.7151522f*(MagickRealType) i;
856 z_map[i].y=0.0721750f*(MagickRealType) i;
857 x_map[i].z=0.0193339f*(MagickRealType) i;
858 y_map[i].z=0.1191920f*(MagickRealType) i;
859 z_map[i].z=0.9503041f*(MagickRealType) i;
866 Initialize YCC tables:
868 Y = 0.29900*R+0.58700*G+0.11400*B
869 C1= -0.29900*R-0.58700*G+0.88600*B
870 C2= 0.70100*R-0.58700*G-0.11400*B
872 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
874 primary_info.y=(double) ScaleQuantumToMap(ScaleCharToQuantum(156));
875 primary_info.z=(double) ScaleQuantumToMap(ScaleCharToQuantum(137));
876 for (i=0; i <= (long) (0.018*MaxMap); i++)
878 x_map[i].x=0.003962014134275617f*(MagickRealType) i;
879 y_map[i].x=0.007778268551236748f*(MagickRealType) i;
880 z_map[i].x=0.001510600706713781f*(MagickRealType) i;
881 x_map[i].y=(-0.002426619775463276f)*(MagickRealType) i;
882 y_map[i].y=(-0.004763965913702149f)*(MagickRealType) i;
883 z_map[i].y=0.007190585689165425f*(MagickRealType) i;
884 x_map[i].z=0.006927257754597858f*(MagickRealType) i;
885 y_map[i].z=(-0.005800713697502058f)*(MagickRealType) i;
886 z_map[i].z=(-0.0011265440570958f)*(MagickRealType) i;
888 for ( ; i <= (long) MaxMap; i++)
890 x_map[i].x=0.2201118963486454*(1.099f*(MagickRealType) i-0.099f);
891 y_map[i].x=0.4321260306242638*(1.099f*(MagickRealType) i-0.099f);
892 z_map[i].x=0.08392226148409894*(1.099f*(MagickRealType) i-0.099f);
893 x_map[i].y=(-0.1348122097479598)*(1.099f*(MagickRealType) i-0.099f);
894 y_map[i].y=(-0.2646647729834528)*(1.099f*(MagickRealType) i-0.099f);
895 z_map[i].y=0.3994769827314126*(1.099f*(MagickRealType) i-0.099f);
896 x_map[i].z=0.3848476530332144*(1.099f*(MagickRealType) i-0.099f);
897 y_map[i].z=(-0.3222618720834477)*(1.099f*(MagickRealType) i-0.099f);
898 z_map[i].z=(-0.06258578094976668)*(1.099f*(MagickRealType) i-0.099f);
905 Initialize YIQ tables:
907 Y = 0.29900*R+0.58700*G+0.11400*B
908 I = 0.59600*R-0.27400*G-0.32200*B
909 Q = 0.21100*R-0.52300*G+0.31200*B
911 I and Q, normally -0.5 through 0.5, are normalized to the range 0
912 through QuantumRange.
914 primary_info.y=(double) (MaxMap+1.0)/2.0;
915 primary_info.z=(double) (MaxMap+1.0)/2.0;
916 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
917 #pragma omp parallel for
919 for (i=0; i <= (long) MaxMap; i++)
921 x_map[i].x=0.29900f*(MagickRealType) i;
922 y_map[i].x=0.58700f*(MagickRealType) i;
923 z_map[i].x=0.11400f*(MagickRealType) i;
924 x_map[i].y=0.59600f*(MagickRealType) i;
925 y_map[i].y=(-0.27400f)*(MagickRealType) i;
926 z_map[i].y=(-0.32200f)*(MagickRealType) i;
927 x_map[i].z=0.21100f*(MagickRealType) i;
928 y_map[i].z=(-0.52300f)*(MagickRealType) i;
929 z_map[i].z=0.31200f*(MagickRealType) i;
933 case YPbPrColorspace:
936 Initialize YPbPr tables (ITU-R BT.601):
938 Y = 0.299000*R+0.587000*G+0.114000*B
939 Pb= -0.168736*R-0.331264*G+0.500000*B
940 Pr= 0.500000*R-0.418688*G-0.081312*B
942 Pb and Pr, normally -0.5 through 0.5, are normalized to the range 0
943 through QuantumRange.
945 primary_info.y=(double) (MaxMap+1.0)/2.0;
946 primary_info.z=(double) (MaxMap+1.0)/2.0;
947 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
948 #pragma omp parallel for
950 for (i=0; i <= (long) MaxMap; i++)
952 x_map[i].x=0.299000f*(MagickRealType) i;
953 y_map[i].x=0.587000f*(MagickRealType) i;
954 z_map[i].x=0.114000f*(MagickRealType) i;
955 x_map[i].y=(-0.168736f)*(MagickRealType) i;
956 y_map[i].y=(-0.331264f)*(MagickRealType) i;
957 z_map[i].y=0.500000f*(MagickRealType) i;
958 x_map[i].z=0.500000f*(MagickRealType) i;
959 y_map[i].z=(-0.418688f)*(MagickRealType) i;
960 z_map[i].z=(-0.081312f)*(MagickRealType) i;
968 Initialize YUV tables:
970 Y = 0.29900*R+0.58700*G+0.11400*B
971 U = -0.14740*R-0.28950*G+0.43690*B
972 V = 0.61500*R-0.51500*G-0.10000*B
974 U and V, normally -0.5 through 0.5, are normalized to the range 0
975 through QuantumRange. Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
977 primary_info.y=(double) (MaxMap+1.0)/2.0;
978 primary_info.z=(double) (MaxMap+1.0)/2.0;
979 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
980 #pragma omp parallel for
982 for (i=0; i <= (long) MaxMap; i++)
984 x_map[i].x=0.29900f*(MagickRealType) i;
985 y_map[i].x=0.58700f*(MagickRealType) i;
986 z_map[i].x=0.11400f*(MagickRealType) i;
987 x_map[i].y=(-0.14740f)*(MagickRealType) i;
988 y_map[i].y=(-0.28950f)*(MagickRealType) i;
989 z_map[i].y=0.43690f*(MagickRealType) i;
990 x_map[i].z=0.61500f*(MagickRealType) i;
991 y_map[i].z=(-0.51500f)*(MagickRealType) i;
992 z_map[i].z=(-0.10000f)*(MagickRealType) i;
1000 switch (image->storage_class)
1006 Convert DirectClass image.
1008 image_view=AcquireCacheView(image);
1009 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1010 #pragma omp parallel for shared(status)
1012 for (y=0; y < (long) image->rows; y++)
1020 register PixelPacket
1023 register unsigned long
1028 if (status == MagickFalse)
1030 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1032 if (q == (PixelPacket *) NULL)
1037 for (x=0; x < (long) image->columns; x++)
1039 red=ScaleQuantumToMap(q->red);
1040 green=ScaleQuantumToMap(q->green);
1041 blue=ScaleQuantumToMap(q->blue);
1042 pixel.red=(x_map[red].x+y_map[green].x+z_map[blue].x)+
1043 (MagickRealType) primary_info.x;
1044 pixel.green=(x_map[red].y+y_map[green].y+z_map[blue].y)+
1045 (MagickRealType) primary_info.y;
1046 pixel.blue=(x_map[red].z+y_map[green].z+z_map[blue].z)+
1047 (MagickRealType) primary_info.z;
1048 q->red=ScaleMapToQuantum(pixel.red);
1049 q->green=ScaleMapToQuantum(pixel.green);
1050 q->blue=ScaleMapToQuantum(pixel.blue);
1053 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1054 if (sync == MagickFalse)
1056 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1061 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1062 #pragma omp critical (MagickCore_RGBTransformImage)
1064 proceed=SetImageProgress(image,RGBTransformImageTag,progress++,
1066 if (proceed == MagickFalse)
1070 image_view=DestroyCacheView(image_view);
1075 register unsigned long
1081 Convert PseudoClass image.
1083 image_view=AcquireCacheView(image);
1084 for (i=0; i < (long) image->colors; i++)
1089 red=ScaleQuantumToMap(image->colormap[i].red);
1090 green=ScaleQuantumToMap(image->colormap[i].green);
1091 blue=ScaleQuantumToMap(image->colormap[i].blue);
1092 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x+primary_info.x;
1093 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y+primary_info.y;
1094 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z+primary_info.z;
1095 image->colormap[i].red=ScaleMapToQuantum(pixel.red);
1096 image->colormap[i].green=ScaleMapToQuantum(pixel.green);
1097 image->colormap[i].blue=ScaleMapToQuantum(pixel.blue);
1099 image_view=DestroyCacheView(image_view);
1100 (void) SyncImage(image);
1105 Relinquish resources.
1107 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1108 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1109 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1110 if (SetImageColorspace(image,colorspace) == MagickFalse)
1111 return(MagickFalse);
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120 % S e t I m a g e C o l o r s p a c e %
1124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1126 % SetImageColorspace() sets the colorspace member of the Image structure.
1128 % The format of the SetImageColorspace method is:
1130 % MagickBooleanType SetImageColorspace(Image *image,
1131 % const ColorspaceType colorspace)
1133 % A description of each parameter follows:
1135 % o image: the image.
1137 % o colorspace: the colorspace.
1140 MagickExport MagickBooleanType SetImageColorspace(Image *image,
1141 const ColorspaceType colorspace)
1146 if (image->colorspace == colorspace)
1148 image->colorspace=colorspace;
1149 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
1150 image->colorspace=colorspace; /* GRAY colorspace might get reset to RGB */
1151 return(cache == (Cache) NULL ? MagickFalse: MagickTrue);
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1159 % T r a n s f o r m I m a g e C o l o r s p a c e %
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 % TransformImageColorspace() transforms an image colorspace.
1167 % The format of the TransformImageColorspace method is:
1169 % MagickBooleanType TransformImageColorspace(Image *image,
1170 % const ColorspaceType colorspace)
1172 % A description of each parameter follows:
1174 % o image: the image.
1176 % o colorspace: the colorspace.
1179 MagickExport MagickBooleanType TransformImageColorspace(Image *image,
1180 const ColorspaceType colorspace)
1185 assert(image != (Image *) NULL);
1186 assert(image->signature == MagickSignature);
1187 if (image->debug != MagickFalse)
1188 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1189 if (colorspace == UndefinedColorspace)
1191 if (SetImageColorspace(image,colorspace) == MagickFalse)
1192 return(MagickFalse);
1195 if (image->colorspace == colorspace)
1197 if ((colorspace == RGBColorspace) || (colorspace == TransparentColorspace))
1198 return(TransformRGBImage(image,image->colorspace));
1200 if ((image->colorspace != RGBColorspace) &&
1201 (image->colorspace != TransparentColorspace) &&
1202 (image->colorspace != GRAYColorspace))
1203 status=TransformRGBImage(image,image->colorspace);
1204 if (RGBTransformImage(image,colorspace) == MagickFalse)
1210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1214 + T r a n s f o r m R G B I m a g e %
1218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220 % TransformRGBImage() converts the reference image from an alternate
1221 % colorspace to RGB. The transformation matrices are not the standard ones:
1222 % the weights are rescaled to normalize the range of the transformed values to
1223 % be [0..QuantumRange].
1225 % The format of the TransformRGBImage method is:
1227 % MagickBooleanType TransformRGBImage(Image *image,
1228 % const ColorspaceType colorspace)
1230 % A description of each parameter follows:
1232 % o image: the image.
1234 % o colorspace: the colorspace to transform the image to.
1238 static inline void ConvertLabToXYZ(const double L,const double a,const double b,
1239 double *X,double *Y,double *Z)
1247 assert(X != (double *) NULL);
1248 assert(Y != (double *) NULL);
1249 assert(Z != (double *) NULL);
1250 y=(100.0*L+16.0)/116.0;
1251 x=255.0*(a > 0.5 ? a-1.0 : a)/500.0+y;
1252 z=y-255.0*(b > 0.5 ? b-1.0 : b)/200.0;
1254 if (cube > 0.008856)
1257 y=(y-16.0/116.0)/7.787;
1259 if (cube > 0.008856)
1262 x=(x-16.0/116.0)/7.787;
1264 if (cube > 0.008856)
1267 z=(z-16.0/116.0)/7.787;
1273 static inline unsigned short RoundToYCC(const MagickRealType value)
1279 return((unsigned short) (value+0.5));
1282 static inline void ConvertXYZToRGB(const double x,const double y,const double z,
1283 Quantum *red,Quantum *green,Quantum *blue)
1291 Convert XYZ to RGB colorspace.
1293 assert(red != (Quantum *) NULL);
1294 assert(green != (Quantum *) NULL);
1295 assert(blue != (Quantum *) NULL);
1296 r=3.2404542*x-1.5371385*y-0.4985314*z;
1297 g=(-0.9692660*x+1.8760108*y+0.0415560*z);
1298 b=0.0556434*x-0.2040259*y+1.0572252*z;
1300 r=1.055*pow(r,1.0/2.4)-0.055;
1304 g=1.055*pow(g,1.0/2.4)-0.055;
1308 b=1.055*pow(b,1.0/2.4)-0.055;
1311 *red=RoundToQuantum((MagickRealType) QuantumRange*r);
1312 *green=RoundToQuantum((MagickRealType) QuantumRange*g);
1313 *blue=RoundToQuantum((MagickRealType) QuantumRange*b);
1316 static inline void ConvertCMYKToRGB(MagickPixelPacket *pixel)
1318 pixel->red=(MagickRealType) QuantumRange-(QuantumScale*pixel->red*
1319 (QuantumRange-pixel->index)+pixel->index);
1320 pixel->green=(MagickRealType) QuantumRange-(QuantumScale*pixel->green*
1321 (QuantumRange-pixel->index)+pixel->index);
1322 pixel->blue=(MagickRealType) QuantumRange-(QuantumScale*pixel->blue*
1323 (QuantumRange-pixel->index)+pixel->index);
1326 MagickExport MagickBooleanType TransformRGBImage(Image *image,
1327 const ColorspaceType colorspace)
1329 #define D50X (0.9642)
1331 #define D50Z (0.8249)
1332 #define TransformRGBImageTag "Transform/Image"
1334 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1335 static const unsigned char
1336 YCCMap[351] = /* Photo CD information beyond 100% white, Gamma 2.2 */
1338 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1339 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
1340 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
1341 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58,
1342 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73,
1343 74, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89,
1344 90, 91, 92, 93, 94, 95, 97, 98, 99, 100, 101, 102, 103, 104,
1345 105, 106, 107, 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
1346 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134,
1347 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
1348 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
1349 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
1350 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
1351 190, 191, 192, 193, 193, 194, 195, 196, 197, 198, 199, 200, 201, 201,
1352 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 211, 212, 213,
1353 214, 215, 215, 216, 217, 218, 218, 219, 220, 221, 221, 222, 223, 224,
1354 224, 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232, 233,
1355 234, 234, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240, 241, 241,
1356 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247,
1357 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 251, 251, 251,
1358 251, 251, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253,
1359 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254,
1360 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255,
1361 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1362 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1388 assert(image != (Image *) NULL);
1389 assert(image->signature == MagickSignature);
1390 if (image->debug != MagickFalse)
1391 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1394 case GRAYColorspace:
1395 case Rec601LumaColorspace:
1396 case Rec709LumaColorspace:
1398 case TransparentColorspace:
1399 case UndefinedColorspace:
1406 exception=(&image->exception);
1412 Transform image from CMY to RGB.
1414 if (image->storage_class == PseudoClass)
1416 if (SyncImage(image) == MagickFalse)
1417 return(MagickFalse);
1418 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1419 return(MagickFalse);
1421 image_view=AcquireCacheView(image);
1422 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1423 #pragma omp parallel for shared(status)
1425 for (y=0; y < (long) image->rows; y++)
1433 register PixelPacket
1436 if (status == MagickFalse)
1438 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1440 if (q == (PixelPacket *) NULL)
1445 for (x=0; x < (long) image->columns; x++)
1447 q->red=RoundToQuantum((MagickRealType) (QuantumRange-q->red));
1448 q->green=RoundToQuantum((MagickRealType) (QuantumRange-q->green));
1449 q->blue=RoundToQuantum((MagickRealType) (QuantumRange-q->blue));
1452 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1453 if (sync == MagickFalse)
1456 image_view=DestroyCacheView(image_view);
1457 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1458 return(MagickFalse);
1461 case CMYKColorspace:
1467 Transform image from CMYK to RGB.
1469 if (image->storage_class == PseudoClass)
1471 if (SyncImage(image) == MagickFalse)
1472 return(MagickFalse);
1473 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1474 return(MagickFalse);
1476 GetMagickPixelPacket(image,&zero);
1477 image_view=AcquireCacheView(image);
1478 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1479 #pragma omp parallel for shared(status)
1481 for (y=0; y < (long) image->rows; y++)
1489 register IndexPacket
1490 *__restrict indexes;
1495 register PixelPacket
1498 if (status == MagickFalse)
1500 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1502 if (q == (PixelPacket *) NULL)
1507 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1509 for (x=0; x < (long) image->columns; x++)
1511 SetMagickPixelPacket(image,q,indexes+x,&pixel);
1512 ConvertCMYKToRGB(&pixel);
1513 SetPixelPacket(image,&pixel,q,indexes+x);
1516 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1517 if (sync == MagickFalse)
1520 image_view=DestroyCacheView(image_view);
1521 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1522 return(MagickFalse);
1528 Transform image from HSB to RGB.
1530 if (image->storage_class == PseudoClass)
1532 if (SyncImage(image) == MagickFalse)
1533 return(MagickFalse);
1534 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1535 return(MagickFalse);
1537 image_view=AcquireCacheView(image);
1538 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1539 #pragma omp parallel for shared(status)
1541 for (y=0; y < (long) image->rows; y++)
1554 register PixelPacket
1557 if (status == MagickFalse)
1559 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1561 if (q == (PixelPacket *) NULL)
1566 for (x=0; x < (long) image->columns; x++)
1568 hue=(double) (QuantumScale*q->red);
1569 saturation=(double) (QuantumScale*q->green);
1570 brightness=(double) (QuantumScale*q->blue);
1571 ConvertHSBToRGB(hue,saturation,brightness,&q->red,&q->green,&q->blue);
1574 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1575 if (sync == MagickFalse)
1578 image_view=DestroyCacheView(image_view);
1579 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1580 return(MagickFalse);
1586 Transform image from HSL to RGB.
1588 if (image->storage_class == PseudoClass)
1590 if (SyncImage(image) == MagickFalse)
1591 return(MagickFalse);
1592 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1593 return(MagickFalse);
1595 image_view=AcquireCacheView(image);
1596 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1597 #pragma omp parallel for shared(status)
1599 for (y=0; y < (long) image->rows; y++)
1612 register PixelPacket
1615 if (status == MagickFalse)
1617 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1619 if (q == (PixelPacket *) NULL)
1624 for (x=0; x < (long) image->columns; x++)
1626 hue=(double) (QuantumScale*q->red);
1627 saturation=(double) (QuantumScale*q->green);
1628 lightness=(double) (QuantumScale*q->blue);
1629 ConvertHSLToRGB(hue,saturation,lightness,&q->red,&q->green,&q->blue);
1632 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1633 if (sync == MagickFalse)
1636 image_view=DestroyCacheView(image_view);
1637 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1638 return(MagickFalse);
1644 Transform image from HWB to RGB.
1646 if (image->storage_class == PseudoClass)
1648 if (SyncImage(image) == MagickFalse)
1649 return(MagickFalse);
1650 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1651 return(MagickFalse);
1653 image_view=AcquireCacheView(image);
1654 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1655 #pragma omp parallel for shared(status)
1657 for (y=0; y < (long) image->rows; y++)
1670 register PixelPacket
1673 if (status == MagickFalse)
1675 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1677 if (q == (PixelPacket *) NULL)
1682 for (x=0; x < (long) image->columns; x++)
1684 hue=(double) (QuantumScale*q->red);
1685 whiteness=(double) (QuantumScale*q->green);
1686 blackness=(double) (QuantumScale*q->blue);
1687 ConvertHWBToRGB(hue,whiteness,blackness,&q->red,&q->green,&q->blue);
1690 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1691 if (sync == MagickFalse)
1694 image_view=DestroyCacheView(image_view);
1695 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1696 return(MagickFalse);
1702 Transform image from Lab to RGB.
1704 if (image->storage_class == PseudoClass)
1706 if (SyncImage(image) == MagickFalse)
1707 return(MagickFalse);
1708 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1709 return(MagickFalse);
1711 image_view=AcquireCacheView(image);
1712 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1713 #pragma omp parallel for shared(status)
1715 for (y=0; y < (long) image->rows; y++)
1731 register PixelPacket
1734 if (status == MagickFalse)
1736 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1738 if (q == (PixelPacket *) NULL)
1746 for (x=0; x < (long) image->columns; x++)
1748 L=QuantumScale*q->red;
1749 a=QuantumScale*q->green;
1750 b=QuantumScale*q->blue;
1751 ConvertLabToXYZ(L,a,b,&X,&Y,&Z);
1752 ConvertXYZToRGB(X,Y,Z,&q->red,&q->green,&q->blue);
1755 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1756 if (sync == MagickFalse)
1759 image_view=DestroyCacheView(image_view);
1760 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1761 return(MagickFalse);
1780 Transform Log to RGB colorspace.
1784 value=GetImageProperty(image,"gamma");
1785 if (value != (const char *) NULL)
1786 gamma=1.0/atof(value) != 0.0 ? atof(value) : 1.0;
1787 reference_black=ReferenceBlack;
1788 value=GetImageProperty(image,"reference-black");
1789 if (value != (const char *) NULL)
1790 reference_black=atof(value);
1791 reference_white=ReferenceWhite;
1792 value=GetImageProperty(image,"reference-white");
1793 if (value != (const char *) NULL)
1794 reference_white=atof(value);
1795 logmap=(Quantum *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1797 if (logmap == (Quantum *) NULL)
1798 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1800 black=pow(10.0,(reference_black-reference_white)*(gamma/density)*
1802 for (i=0; i <= (long) (reference_black*MaxMap/1024.0); i++)
1803 logmap[i]=(Quantum) 0;
1804 for ( ; i < (long) (reference_white*MaxMap/1024.0); i++)
1805 logmap[i]=RoundToQuantum((MagickRealType) QuantumRange/(1.0-black)*
1806 (pow(10.0,(1024.0*i/MaxMap-reference_white)*
1807 (gamma/density)*0.002/0.6)-black));
1808 for ( ; i <= (long) MaxMap; i++)
1809 logmap[i]=(Quantum) QuantumRange;
1810 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1811 return(MagickFalse);
1812 image_view=AcquireCacheView(image);
1813 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1814 #pragma omp parallel for shared(status)
1816 for (y=0; y < (long) image->rows; y++)
1824 register PixelPacket
1827 if (status == MagickFalse)
1829 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
1831 if (q == (PixelPacket *) NULL)
1836 for (x=(long) image->columns; x != 0; x--)
1838 q->red=logmap[ScaleQuantumToMap(q->red)];
1839 q->green=logmap[ScaleQuantumToMap(q->green)];
1840 q->blue=logmap[ScaleQuantumToMap(q->blue)];
1843 sync=SyncCacheViewAuthenticPixels(image_view,exception);
1844 if (sync == MagickFalse)
1847 image_view=DestroyCacheView(image_view);
1848 logmap=(Quantum *) RelinquishMagickMemory(logmap);
1849 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
1850 return(MagickFalse);
1857 Allocate the tables.
1859 x_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1861 y_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1863 z_map=(TransformPacket *) AcquireQuantumMemory((size_t) MaxMap+1UL,
1865 if ((x_map == (TransformPacket *) NULL) ||
1866 (y_map == (TransformPacket *) NULL) ||
1867 (z_map == (TransformPacket *) NULL))
1869 if (z_map != (TransformPacket *) NULL)
1870 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
1871 if (y_map != (TransformPacket *) NULL)
1872 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
1873 if (x_map != (TransformPacket *) NULL)
1874 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
1875 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1880 case OHTAColorspace:
1883 Initialize OHTA tables:
1885 R = I1+1.00000*I2-0.66668*I3
1886 G = I1+0.00000*I2+1.33333*I3
1887 B = I1-1.00000*I2-0.66668*I3
1889 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
1890 through QuantumRange.
1892 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1893 #pragma omp parallel for
1895 for (i=0; i <= (long) MaxMap; i++)
1897 x_map[i].x=(MagickRealType) i;
1898 y_map[i].x=0.500000f*(2.000000*(MagickRealType) i-(MagickRealType)
1900 z_map[i].x=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1902 x_map[i].y=(MagickRealType) i;
1903 y_map[i].y=0.000000f;
1904 z_map[i].y=0.666665f*(2.000000f*(MagickRealType) i-(MagickRealType)
1906 x_map[i].z=(MagickRealType) i;
1907 y_map[i].z=(-0.500000f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1909 z_map[i].z=(-0.333340f)*(2.000000f*(MagickRealType) i-(MagickRealType)
1914 case Rec601YCbCrColorspace:
1915 case YCbCrColorspace:
1918 Initialize YCbCr tables:
1921 G = Y-0.344136*Cb-0.714136*Cr
1924 Cb and Cr, normally -0.5 through 0.5, must be normalized to the range 0
1925 through QuantumRange.
1927 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1928 #pragma omp parallel for
1930 for (i=0; i <= (long) MaxMap; i++)
1932 x_map[i].x=(MagickRealType) i;
1933 y_map[i].x=0.000000f;
1934 z_map[i].x=(1.402000f*0.500000f)*(2.000000f*(MagickRealType) i-
1935 (MagickRealType) MaxMap);
1936 x_map[i].y=(MagickRealType) i;
1937 y_map[i].y=(-0.344136f*0.500000f)*(2.000000f*(MagickRealType) i-
1938 (MagickRealType) MaxMap);
1939 z_map[i].y=(-0.714136f*0.500000f)*(2.000000f*(MagickRealType) i-
1940 (MagickRealType) MaxMap);
1941 x_map[i].z=(MagickRealType) i;
1942 y_map[i].z=(1.772000f*0.500000f)*(2.000000f*(MagickRealType) i-
1943 (MagickRealType) MaxMap);
1944 z_map[i].z=0.000000f;
1948 case Rec709YCbCrColorspace:
1951 Initialize YCbCr tables:
1954 G = Y-0.187324*Cb-0.468124*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) && (_OPENMP >= 200203)
1961 #pragma omp parallel for
1963 for (i=0; i <= (long) MaxMap; i++)
1965 x_map[i].x=(MagickRealType) i;
1966 y_map[i].x=0.000000f;
1967 z_map[i].x=(1.574800f*0.50000f)*(2.00000f*(MagickRealType) i-
1968 (MagickRealType) MaxMap);
1969 x_map[i].y=(MagickRealType) i;
1970 y_map[i].y=(-0.187324f*0.50000f)*(2.00000f*(MagickRealType) i-
1971 (MagickRealType) MaxMap);
1972 z_map[i].y=(-0.468124f*0.50000f)*(2.00000f*(MagickRealType) i-
1973 (MagickRealType) MaxMap);
1974 x_map[i].z=(MagickRealType) i;
1975 y_map[i].z=(1.855600f*0.50000f)*(2.00000f*(MagickRealType) i-
1976 (MagickRealType) MaxMap);
1977 z_map[i].z=0.00000f;
1981 case sRGBColorspace:
1984 Nonlinear sRGB to linear RGB.
1986 R = 1.0*R+0.0*G+0.0*B
1987 G = 0.0*R+1.0*G+0.0*B
1988 B = 0.0*R+0.0*G+1.0*B
1990 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
1991 #pragma omp parallel for
1993 for (i=0; i <= (long) MaxMap; i++)
1995 x_map[i].x=1.0f*(MagickRealType) i;
1996 y_map[i].x=0.0f*(MagickRealType) i;
1997 z_map[i].x=0.0f*(MagickRealType) i;
1998 x_map[i].y=0.0f*(MagickRealType) i;
1999 y_map[i].y=1.0f*(MagickRealType) i;
2000 z_map[i].y=0.0f*(MagickRealType) i;
2001 x_map[i].z=0.0f*(MagickRealType) i;
2002 y_map[i].z=0.0f*(MagickRealType) i;
2003 z_map[i].z=1.0f*(MagickRealType) i;
2010 Initialize CIE XYZ tables (ITU R-709 RGB):
2012 R = 3.2404542*X-1.5371385*Y-0.4985314*Z
2013 G = -0.9692660*X+1.8760108*Y+0.0415560*Z
2014 B = 0.0556434*X-0.2040259*Y+1.057225*Z
2016 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2017 #pragma omp parallel for
2019 for (i=0; i <= (long) MaxMap; i++)
2021 x_map[i].x=3.2404542f*(MagickRealType) i;
2022 x_map[i].y=(-0.9692660f)*(MagickRealType) i;
2023 x_map[i].z=0.0556434f*(MagickRealType) i;
2024 y_map[i].x=(-1.5371385f)*(MagickRealType) i;
2025 y_map[i].y=1.8760108f*(MagickRealType) i;
2026 y_map[i].z=(-0.2040259f)*(MagickRealType) i;
2027 z_map[i].x=(-0.4985314f)*(MagickRealType) i;
2028 z_map[i].y=0.0415560f*(MagickRealType) i;
2029 z_map[i].z=1.0572252f*(MagickRealType) i;
2036 Initialize YCC tables:
2039 G = Y-0.317038*C1-0.682243*C2
2042 YCC is scaled by 1.3584. C1 zero is 156 and C2 is at 137.
2044 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2045 #pragma omp parallel for
2047 for (i=0; i <= (long) MaxMap; i++)
2049 x_map[i].x=1.3584000f*(MagickRealType) i;
2050 y_map[i].x=0.0000000f;
2051 z_map[i].x=1.8215000f*((MagickRealType) i-(MagickRealType)
2052 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2053 x_map[i].y=1.3584000f*(MagickRealType) i;
2054 y_map[i].y=(-0.4302726f)*((MagickRealType) i-(MagickRealType)
2055 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2056 z_map[i].y=(-0.9271435f)*((MagickRealType) i-(MagickRealType)
2057 ScaleQuantumToMap(ScaleCharToQuantum(137)));
2058 x_map[i].z=1.3584000f*(MagickRealType) i;
2059 y_map[i].z=2.2179000f*((MagickRealType) i-(MagickRealType)
2060 ScaleQuantumToMap(ScaleCharToQuantum(156)));
2061 z_map[i].z=0.0000000f;
2068 Initialize YIQ tables:
2070 R = Y+0.95620*I+0.62140*Q
2071 G = Y-0.27270*I-0.64680*Q
2072 B = Y-1.10370*I+1.70060*Q
2074 I and Q, normally -0.5 through 0.5, must be normalized to the range 0
2075 through QuantumRange.
2077 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2078 #pragma omp parallel for
2080 for (i=0; i <= (long) MaxMap; i++)
2082 x_map[i].x=(MagickRealType) i;
2083 y_map[i].x=0.47810f*(2.00000f*(MagickRealType) i-(MagickRealType)
2085 z_map[i].x=0.31070f*(2.00000f*(MagickRealType) i-(MagickRealType)
2087 x_map[i].y=(MagickRealType) i;
2088 y_map[i].y=(-0.13635f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2090 z_map[i].y=(-0.32340f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2092 x_map[i].z=(MagickRealType) i;
2093 y_map[i].z=(-0.55185f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2095 z_map[i].z=0.85030f*(2.00000f*(MagickRealType) i-(MagickRealType)
2100 case YPbPrColorspace:
2103 Initialize YPbPr tables:
2106 G = Y-0.344136*C1+0.714136*C2
2109 Pb and Pr, normally -0.5 through 0.5, must be normalized to the range 0
2110 through QuantumRange.
2112 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2113 #pragma omp parallel for
2115 for (i=0; i <= (long) MaxMap; i++)
2117 x_map[i].x=(MagickRealType) i;
2118 y_map[i].x=0.000000f;
2119 z_map[i].x=0.701000f*(2.00000f*(MagickRealType) i-(MagickRealType)
2121 x_map[i].y=(MagickRealType) i;
2122 y_map[i].y=(-0.172068f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2124 z_map[i].y=0.357068f*(2.00000f*(MagickRealType) i-(MagickRealType)
2126 x_map[i].z=(MagickRealType) i;
2127 y_map[i].z=0.88600f*(2.00000f*(MagickRealType) i-(MagickRealType)
2129 z_map[i].z=0.00000f;
2137 Initialize YUV tables:
2140 G = Y-0.39380*U-0.58050*V
2143 U and V, normally -0.5 through 0.5, must be normalized to the range 0
2144 through QuantumRange.
2146 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2147 #pragma omp parallel for
2149 for (i=0; i <= (long) MaxMap; i++)
2151 x_map[i].x=(MagickRealType) i;
2152 y_map[i].x=0.00000f;
2153 z_map[i].x=0.56990f*(2.0000f*(MagickRealType) i-(MagickRealType)
2155 x_map[i].y=(MagickRealType) i;
2156 y_map[i].y=(-0.19690f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2158 z_map[i].y=(-0.29025f)*(2.00000f*(MagickRealType) i-(MagickRealType)
2160 x_map[i].z=(MagickRealType) i;
2161 y_map[i].z=1.01395f*(2.00000f*(MagickRealType) i-(MagickRealType)
2163 z_map[i].z=0.00000f;
2171 switch (image->storage_class)
2177 Convert DirectClass image.
2179 image_view=AcquireCacheView(image);
2180 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2181 #pragma omp parallel for shared(status)
2183 for (y=0; y < (long) image->rows; y++)
2194 register PixelPacket
2197 if (status == MagickFalse)
2199 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2201 if (q == (PixelPacket *) NULL)
2206 for (x=0; x < (long) image->columns; x++)
2208 register unsigned long
2213 red=ScaleQuantumToMap(q->red);
2214 green=ScaleQuantumToMap(q->green);
2215 blue=ScaleQuantumToMap(q->blue);
2216 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2217 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2218 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2223 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2224 pixel.red=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2225 255.0*QuantumScale*pixel.red)]);
2226 pixel.green=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2227 255.0*QuantumScale*pixel.green)]);
2228 pixel.blue=(MagickRealType) ScaleCharToQuantum(YCCMap[RoundToYCC(
2229 255.0*QuantumScale*pixel.blue)]);
2233 case sRGBColorspace:
2235 if ((QuantumScale*pixel.red) <= 0.0031308)
2238 pixel.red=(MagickRealType) QuantumRange*(1.055*
2239 pow(QuantumScale*pixel.red,(1.0/2.4))-0.055);
2240 if ((QuantumScale*pixel.green) <= 0.0031308)
2241 pixel.green*=12.92f;
2243 pixel.green=(MagickRealType) QuantumRange*(1.055*
2244 pow(QuantumScale*pixel.green,(1.0/2.4))-0.055);
2245 if ((QuantumScale*pixel.blue) <= 0.0031308)
2248 pixel.blue=(MagickRealType) QuantumRange*(1.055*
2249 pow(QuantumScale*pixel.blue,(1.0/2.4))-0.055);
2255 q->red=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2257 q->green=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2259 q->blue=ScaleMapToQuantum((MagickRealType) MaxMap*QuantumScale*
2263 sync=SyncCacheViewAuthenticPixels(image_view,exception);
2264 if (sync == MagickFalse)
2266 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2271 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2272 #pragma omp critical (MagickCore_TransformRGBImage)
2274 proceed=SetImageProgress(image,TransformRGBImageTag,progress++,
2276 if (proceed == MagickFalse)
2280 image_view=DestroyCacheView(image_view);
2286 Convert PseudoClass image.
2288 image_view=AcquireCacheView(image);
2289 #if defined(MAGICKCORE_OPENMP_SUPPORT) && (_OPENMP >= 200203)
2290 #pragma omp parallel for shared(status)
2292 for (i=0; i < (long) image->colors; i++)
2297 register unsigned long
2302 red=ScaleQuantumToMap(image->colormap[i].red);
2303 green=ScaleQuantumToMap(image->colormap[i].green);
2304 blue=ScaleQuantumToMap(image->colormap[i].blue);
2305 pixel.red=x_map[red].x+y_map[green].x+z_map[blue].x;
2306 pixel.green=x_map[red].y+y_map[green].y+z_map[blue].y;
2307 pixel.blue=x_map[red].z+y_map[green].z+z_map[blue].z;
2312 #if !defined(MAGICKCORE_HDRI_SUPPORT)
2313 image->colormap[i].red=ScaleCharToQuantum(YCCMap[RoundToYCC(
2314 255.0*QuantumScale*pixel.red)]);
2315 image->colormap[i].green=ScaleCharToQuantum(YCCMap[RoundToYCC(
2316 255.0*QuantumScale*pixel.green)]);
2317 image->colormap[i].blue=ScaleCharToQuantum(YCCMap[RoundToYCC(
2318 255.0*QuantumScale*pixel.blue)]);
2322 case sRGBColorspace:
2324 if ((QuantumScale*pixel.red) <= 0.0031308)
2327 pixel.red=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2328 pixel.red,(1.0/2.4))-0.055);
2329 if ((QuantumScale*pixel.green) <= 0.0031308)
2330 pixel.green*=12.92f;
2332 pixel.green=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2333 pixel.green,(1.0/2.4))-0.055);
2334 if ((QuantumScale*pixel.blue) <= 0.0031308)
2337 pixel.blue=(MagickRealType) QuantumRange*(1.055*pow(QuantumScale*
2338 pixel.blue,(1.0/2.4))-0.055);
2342 image->colormap[i].red=ScaleMapToQuantum((MagickRealType) MaxMap*
2343 QuantumScale*pixel.red);
2344 image->colormap[i].green=ScaleMapToQuantum((MagickRealType) MaxMap*
2345 QuantumScale*pixel.green);
2346 image->colormap[i].blue=ScaleMapToQuantum((MagickRealType) MaxMap*
2347 QuantumScale*pixel.blue);
2352 image_view=DestroyCacheView(image_view);
2353 (void) SyncImage(image);
2358 Relinquish resources.
2360 z_map=(TransformPacket *) RelinquishMagickMemory(z_map);
2361 y_map=(TransformPacket *) RelinquishMagickMemory(y_map);
2362 x_map=(TransformPacket *) RelinquishMagickMemory(x_map);
2363 if (SetImageColorspace(image,RGBColorspace) == MagickFalse)
2364 return(MagickFalse);