2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Graphic Gems - Graphic Support Methods %
20 % Copyright 1999-2013 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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/color-private.h"
45 #include "MagickCore/draw.h"
46 #include "MagickCore/gem.h"
47 #include "MagickCore/gem-private.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/image-private.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/memory_.h"
52 #include "MagickCore/pixel-accessor.h"
53 #include "MagickCore/pixel-private.h"
54 #include "MagickCore/quantum.h"
55 #include "MagickCore/quantum-private.h"
56 #include "MagickCore/random_.h"
57 #include "MagickCore/resize.h"
58 #include "MagickCore/transform.h"
59 #include "MagickCore/signature-private.h"
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66 % C o n v e r t H C L T o R G B %
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 % ConvertHCLToRGB() transforms a (hue, chroma, luma) to a (red, green,
75 % The format of the ConvertHCLToRGBImage method is:
77 % void ConvertHCLToRGB(const double hue,const double chroma,
78 % const double luma,double *red,double *green,double *blue)
80 % A description of each parameter follows:
82 % o hue, chroma, luma: A double value representing a component of the
85 % o red, green, blue: A pointer to a pixel component of type Quantum.
88 MagickPrivate void ConvertHCLToRGB(const double hue,const double chroma,
89 const double luma,double *red,double *green,double *blue)
101 Convert HCL to RGB colorspace.
103 assert(red != (double *) NULL);
104 assert(green != (double *) NULL);
105 assert(blue != (double *) NULL);
108 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
112 if ((0.0 <= h) && (h < 1.0))
118 if ((1.0 <= h) && (h < 2.0))
124 if ((2.0 <= h) && (h < 3.0))
130 if ((3.0 <= h) && (h < 4.0))
136 if ((4.0 <= h) && (h < 5.0))
142 if ((5.0 <= h) && (h < 6.0))
147 m=luma-(0.298839*r+0.586811*g+0.114350*b);
148 *red=QuantumRange*(r+m);
149 *green=QuantumRange*(g+m);
150 *blue=QuantumRange*(b+m);
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 % C o n v e r t H C L p T o R G B %
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 % ConvertHCLpToRGB() transforms a (hue, chroma, luma) to a (red, green,
165 % blue) triple. Since HCL colorspace is wider than RGB, we instead choose a
166 % saturation strategy to project it on the RGB cube.
168 % The format of the ConvertHCLpToRGBImage method is:
170 % void ConvertHCLpToRGB(const double hue,const double chroma,
171 % const double luma,double *red,double *green,double *blue)
173 % A description of each parameter follows:
175 % o hue, chroma, luma: A double value representing a componenet of the
178 % o red, green, blue: A pointer to a pixel component of type Quantum.
181 MagickPrivate void ConvertHCLpToRGB(const double hue,const double chroma,
182 const double luma,double *red,double *green,double *blue)
195 Convert HCLp to RGB colorspace.
197 assert(red != (double *) NULL);
198 assert(green != (double *) NULL);
199 assert(blue != (double *) NULL);
202 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
206 if ((0.0 <= h) && (h < 1.0))
212 if ((1.0 <= h) && (h < 2.0))
218 if ((2.0 <= h) && (h < 3.0))
224 if ((3.0 <= h) && (h < 4.0))
230 if ((4.0 <= h) && (h < 5.0))
236 if ((5.0 <= h) && (h < 6.0))
241 m=luma-(0.298839*r+0.586811*g+0.114350*b);
251 z=(1.0-luma)/(m+c-luma);
254 *red=QuantumRange*(z*r+m);
255 *green=QuantumRange*(z*g+m);
256 *blue=QuantumRange*(z*b+m);
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264 % C o n v e r t H S B T o R G B %
268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270 % ConvertHSBToRGB() transforms a (hue, saturation, brightness) to a (red,
271 % green, blue) triple.
273 % The format of the ConvertHSBToRGBImage method is:
275 % void ConvertHSBToRGB(const double hue,const double saturation,
276 % const double brightness,double *red,double *green,double *blue)
278 % A description of each parameter follows:
280 % o hue, saturation, brightness: A double value representing a
281 % component of the HSB color space.
283 % o red, green, blue: A pointer to a pixel component of type Quantum.
286 MagickPrivate void ConvertHSBToRGB(const double hue,const double saturation,
287 const double brightness,double *red,double *green,double *blue)
297 Convert HSB to RGB colorspace.
299 assert(red != (double *) NULL);
300 assert(green != (double *) NULL);
301 assert(blue != (double *) NULL);
302 if (saturation == 0.0)
304 *red=QuantumRange*brightness;
309 h=6.0*(hue-floor(hue));
310 f=h-floor((double) h);
311 p=brightness*(1.0-saturation);
312 q=brightness*(1.0-saturation*f);
313 t=brightness*(1.0-(saturation*(1.0-f)));
319 *red=QuantumRange*brightness;
320 *green=QuantumRange*t;
321 *blue=QuantumRange*p;
327 *green=QuantumRange*brightness;
328 *blue=QuantumRange*p;
334 *green=QuantumRange*brightness;
335 *blue=QuantumRange*t;
341 *green=QuantumRange*q;
342 *blue=QuantumRange*brightness;
348 *green=QuantumRange*p;
349 *blue=QuantumRange*brightness;
354 *red=QuantumRange*brightness;
355 *green=QuantumRange*p;
356 *blue=QuantumRange*q;
363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % C o n v e r t H S I T o R G B %
371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 % ConvertHSIToRGB() transforms a (hue, saturation, intensity) to a (red,
374 % green, blue) triple.
376 % The format of the ConvertHSIToRGBImage method is:
378 % void ConvertHSIToRGB(const double hue,const double saturation,
379 % const double intensity,double *red,double *green,double *blue)
381 % A description of each parameter follows:
383 % o hue, saturation, intensity: A double value representing a
384 % component of the HSI color space.
386 % o red, green, blue: A pointer to a pixel component of type Quantum.
389 MagickPrivate void ConvertHSIToRGB(const double hue,const double saturation,
390 const double intensity,double *red,double *green,double *blue)
399 Convert HSI to RGB colorspace.
401 assert(red != (double *) NULL);
402 assert(green != (double *) NULL);
403 assert(blue != (double *) NULL);
405 h-=360.0*floor(h/360.0);
408 b=intensity*(1.0-saturation);
409 r=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
417 r=intensity*(1.0-saturation);
418 g=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
425 g=intensity*(1.0-saturation);
426 b=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
431 *green=QuantumRange*g;
432 *blue=QuantumRange*b;
436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440 % C o n v e r t H S L T o R G B %
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
447 % green, blue) triple.
449 % The format of the ConvertHSLToRGBImage method is:
451 % void ConvertHSLToRGB(const double hue,const double saturation,
452 % const double lightness,double *red,double *green,double *blue)
454 % A description of each parameter follows:
456 % o hue, saturation, lightness: A double value representing a
457 % component of the HSL color space.
459 % o red, green, blue: A pointer to a pixel component of type Quantum.
462 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
463 const double lightness,double *red,double *green,double *blue)
472 Convert HSL to RGB colorspace.
474 assert(red != (double *) NULL);
475 assert(green != (double *) NULL);
476 assert(blue != (double *) NULL);
478 if (lightness <= 0.5)
479 c=2.0*lightness*saturation;
481 c=(2.0-2.0*lightness)*saturation;
483 h-=360.0*floor(h/360.0);
485 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
486 switch ((int) floor(h))
490 *red=QuantumRange*(min+c);
491 *green=QuantumRange*(min+x);
492 *blue=QuantumRange*min;
497 *red=QuantumRange*(min+x);
498 *green=QuantumRange*(min+c);
499 *blue=QuantumRange*min;
504 *red=QuantumRange*min;
505 *green=QuantumRange*(min+c);
506 *blue=QuantumRange*(min+x);
511 *red=QuantumRange*min;
512 *green=QuantumRange*(min+x);
513 *blue=QuantumRange*(min+c);
518 *red=QuantumRange*(min+x);
519 *green=QuantumRange*min;
520 *blue=QuantumRange*(min+c);
525 *red=QuantumRange*(min+c);
526 *green=QuantumRange*min;
527 *blue=QuantumRange*(min+x);
540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 % C o n v e r t H S V T o R G B %
548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 % ConvertHSVToRGB() transforms a (hue, saturation, value) to a (red,
551 % green, blue) triple.
553 % The format of the ConvertHSVToRGBImage method is:
555 % void ConvertHSVToRGB(const double hue,const double saturation,
556 % const double value,double *red,double *green,double *blue)
558 % A description of each parameter follows:
560 % o hue, saturation, value: A double value representing a
561 % component of the HSV color space.
563 % o red, green, blue: A pointer to a pixel component of type Quantum.
566 MagickPrivate void ConvertHSVToRGB(const double hue,const double saturation,
567 const double value,double *red,double *green,double *blue)
576 Convert HSV to RGB colorspace.
578 assert(red != (double *) NULL);
579 assert(green != (double *) NULL);
580 assert(blue != (double *) NULL);
584 h-=360.0*floor(h/360.0);
586 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
587 switch ((int) floor(h))
591 *red=QuantumRange*(min+c);
592 *green=QuantumRange*(min+x);
593 *blue=QuantumRange*min;
598 *red=QuantumRange*(min+x);
599 *green=QuantumRange*(min+c);
600 *blue=QuantumRange*min;
605 *red=QuantumRange*min;
606 *green=QuantumRange*(min+c);
607 *blue=QuantumRange*(min+x);
612 *red=QuantumRange*min;
613 *green=QuantumRange*(min+x);
614 *blue=QuantumRange*(min+c);
619 *red=QuantumRange*(min+x);
620 *green=QuantumRange*min;
621 *blue=QuantumRange*(min+c);
626 *red=QuantumRange*(min+c);
627 *green=QuantumRange*min;
628 *blue=QuantumRange*(min+x);
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645 % C o n v e r t H W B T o R G B %
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
654 % The format of the ConvertHWBToRGBImage method is:
656 % void ConvertHWBToRGB(const double hue,const double whiteness,
657 % const double blackness,double *red,double *green,double *blue)
659 % A description of each parameter follows:
661 % o hue, whiteness, blackness: A double value representing a
662 % component of the HWB color space.
664 % o red, green, blue: A pointer to a pixel component of type Quantum.
667 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
668 const double blackness,double *red,double *green,double *blue)
682 Convert HWB to RGB colorspace.
684 assert(red != (double *) NULL);
685 assert(green != (double *) NULL);
686 assert(blue != (double *) NULL);
691 *green=QuantumRange*v;
692 *blue=QuantumRange*v;
695 i=(ssize_t) floor(6.0*hue);
699 n=whiteness+f*(v-whiteness); /* linear interpolation */
704 case 0: r=v; g=n; b=whiteness; break;
705 case 1: r=n; g=v; b=whiteness; break;
706 case 2: r=whiteness; g=v; b=n; break;
707 case 3: r=whiteness; g=n; b=v; break;
708 case 4: r=n; g=whiteness; b=v; break;
709 case 5: r=v; g=whiteness; b=n; break;
712 *green=QuantumRange*g;
713 *blue=QuantumRange*b;
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 % C o n v e r t L C H a b T o R G B %
725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727 % ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green,
730 % The format of the ConvertLCHabToRGBImage method is:
732 % void ConvertLCHabToRGB(const double luma,const double chroma,
733 % const double hue,double *red,double *green,double *blue)
735 % A description of each parameter follows:
737 % o luma, chroma, hue: A double value representing a component of the
740 % o red, green, blue: A pointer to a pixel component of type Quantum.
744 static inline void ConvertLCHabToXYZ(const double luma,const double chroma,
745 const double hue,double *X,double *Y,double *Z)
747 ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
748 sin(hue*MagickPI/180.0),X,Y,Z);
751 MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
752 const double hue,double *red,double *green,double *blue)
760 Convert LCHab to RGB colorspace.
762 assert(red != (double *) NULL);
763 assert(green != (double *) NULL);
764 assert(blue != (double *) NULL);
765 ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*(hue-0.5),&X,&Y,&Z);
766 ConvertXYZToRGB(X,Y,Z,red,green,blue);
770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
774 % C o n v e r t L C H u v T o R G B %
778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
780 % ConvertLCHuvToRGB() transforms a (luma, chroma, hue) to a (red, green,
783 % The format of the ConvertLCHuvToRGBImage method is:
785 % void ConvertLCHuvToRGB(const double luma,const double chroma,
786 % const double hue,double *red,double *green,double *blue)
788 % A description of each parameter follows:
790 % o luma, chroma, hue: A double value representing a component of the
793 % o red, green, blue: A pointer to a pixel component of type Quantum.
797 static inline void ConvertLCHuvToXYZ(const double luma,const double chroma,
798 const double hue,double *X,double *Y,double *Z)
800 ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
801 sin(hue*MagickPI/180.0),X,Y,Z);
804 MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
805 const double hue,double *red,double *green,double *blue)
813 Convert LCHuv to RGB colorspace.
815 assert(red != (double *) NULL);
816 assert(green != (double *) NULL);
817 assert(blue != (double *) NULL);
818 ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*(hue-0.5),&X,&Y,&Z)
819 ConvertXYZToRGB(X,Y,Z,red,green,blue);
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 % C o n v e r t R G B T o H C L %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
836 % The format of the ConvertRGBToHCL method is:
838 % void ConvertRGBToHCL(const double red,const double green,
839 % const double blue,double *hue,double *chroma,double *luma)
841 % A description of each parameter follows:
843 % o red, green, blue: A Quantum value representing the red, green, and
844 % blue component of a pixel.
846 % o hue, chroma, luma: A pointer to a double value representing a
847 % component of the HCL color space.
851 static inline double MagickMax(const double x,const double y)
858 static inline double MagickMin(const double x,const double y)
865 MagickPrivate void ConvertRGBToHCL(const double red,const double green,
866 const double blue,double *hue,double *chroma,double *luma)
877 Convert RGB to HCL colorspace.
879 assert(hue != (double *) NULL);
880 assert(chroma != (double *) NULL);
881 assert(luma != (double *) NULL);
885 max=MagickMax(r,MagickMax(g,b));
886 c=max-(double) MagickMin(r,MagickMin(g,b));
892 h=fmod((g-b)/c+6.0,6.0);
900 *chroma=QuantumScale*c;
901 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909 % C o n v e r t R G B T o H C L p %
913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
915 % ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma,
918 % The format of the ConvertRGBToHCLp method is:
920 % void ConvertRGBToHCLp(const double red,const double green,
921 % const double blue,double *hue,double *chroma,double *luma)
923 % A description of each parameter follows:
925 % o red, green, blue: A Quantum value representing the red, green, and
926 % blue component of a pixel.
928 % o hue, chroma, luma: A pointer to a double value representing a
929 % component of the HCL color space.
932 MagickPrivate void ConvertRGBToHCLp(const double red,const double green,
933 const double blue,double *hue,double *chroma,double *luma)
944 Convert RGB to HCL colorspace.
946 assert(hue != (double *) NULL);
947 assert(chroma != (double *) NULL);
948 assert(luma != (double *) NULL);
952 max=MagickMax(r,MagickMax(g,b));
953 c=max-(double) MagickMin(r,MagickMin(g,b));
959 h=fmod((g-b)/c+6.0,6.0);
967 *chroma=QuantumScale*c;
968 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976 % C o n v e r t R G B T o H S B %
980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
983 % brightness) triple.
985 % The format of the ConvertRGBToHSB method is:
987 % void ConvertRGBToHSB(const double red,const double green,
988 % const double blue,double *hue,double *saturation,double *brightness)
990 % A description of each parameter follows:
992 % o red, green, blue: A Quantum value representing the red, green, and
993 % blue component of a pixel..
995 % o hue, saturation, brightness: A pointer to a double value representing a
996 % component of the HSB color space.
999 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
1000 const double blue,double *hue,double *saturation,double *brightness)
1011 Convert RGB to HSB colorspace.
1013 assert(hue != (double *) NULL);
1014 assert(saturation != (double *) NULL);
1015 assert(brightness != (double *) NULL);
1031 *saturation=delta/max;
1032 *brightness=QuantumScale*max;
1039 *hue=2.0+(b-r)/delta;
1041 *hue=4.0+(r-g)/delta;
1048 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1052 % C o n v e r t R G B T o H S I %
1056 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1058 % ConvertRGBToHSI() transforms a (red, green, blue) to a (hue, saturation,
1059 % intensity) triple.
1061 % The format of the ConvertRGBToHSI method is:
1063 % void ConvertRGBToHSI(const double red,const double green,
1064 % const double blue,double *hue,double *saturation,double *intensity)
1066 % A description of each parameter follows:
1068 % o red, green, blue: A Quantum value representing the red, green, and
1069 % blue component of a pixel..
1071 % o hue, saturation, intensity: A pointer to a double value representing a
1072 % component of the HSI color space.
1075 MagickPrivate void ConvertRGBToHSI(const double red,const double green,
1076 const double blue,double *hue,double *saturation,double *intensity)
1083 Convert RGB to HSI colorspace.
1085 assert(hue != (double *) NULL);
1086 assert(saturation != (double *) NULL);
1087 assert(intensity != (double *) NULL);
1088 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
1089 if (*intensity <= 0.0)
1095 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1096 QuantumScale*blue))/(*intensity);
1097 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
1098 beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
1099 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
1105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 % C o n v e r t R G B T o H S L %
1113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1115 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
1116 % lightness) triple.
1118 % The format of the ConvertRGBToHSL method is:
1120 % void ConvertRGBToHSL(const double red,const double green,
1121 % const double blue,double *hue,double *saturation,double *lightness)
1123 % A description of each parameter follows:
1125 % o red, green, blue: A Quantum value representing the red, green, and
1126 % blue component of a pixel..
1128 % o hue, saturation, lightness: A pointer to a double value representing a
1129 % component of the HSL color space.
1132 MagickExport void ConvertRGBToHSL(const double red,const double green,
1133 const double blue,double *hue,double *saturation,double *lightness)
1141 Convert RGB to HSL colorspace.
1143 assert(hue != (double *) NULL);
1144 assert(saturation != (double *) NULL);
1145 assert(lightness != (double *) NULL);
1146 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1147 QuantumScale*blue));
1148 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1149 QuantumScale*blue));
1151 *lightness=(max+min)/2.0;
1158 if (max == (QuantumScale*red))
1160 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1161 if ((QuantumScale*green) < (QuantumScale*blue))
1165 if (max == (QuantumScale*green))
1166 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1168 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1170 if (*lightness <= 0.5)
1171 *saturation=c/(2.0*(*lightness));
1173 *saturation=c/(2.0-2.0*(*lightness));
1177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1181 % C o n v e r t R G B T o H S V %
1185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187 % ConvertRGBToHSV() transforms a (red, green, blue) to a (hue, saturation,
1190 % The format of the ConvertRGBToHSV method is:
1192 % void ConvertRGBToHSV(const double red,const double green,
1193 % const double blue,double *hue,double *saturation,double *value)
1195 % A description of each parameter follows:
1197 % o red, green, blue: A Quantum value representing the red, green, and
1198 % blue component of a pixel..
1200 % o hue, saturation, value: A pointer to a double value representing a
1201 % component of the HSV color space.
1204 MagickPrivate void ConvertRGBToHSV(const double red,const double green,
1205 const double blue,double *hue,double *saturation,double *value)
1213 Convert RGB to HSV colorspace.
1215 assert(hue != (double *) NULL);
1216 assert(saturation != (double *) NULL);
1217 assert(value != (double *) NULL);
1218 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1219 QuantumScale*blue));
1220 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1221 QuantumScale*blue));
1230 if (max == (QuantumScale*red))
1232 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1233 if ((QuantumScale*green) < (QuantumScale*blue))
1237 if (max == (QuantumScale*green))
1238 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1240 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1250 % C o n v e r t R G B T o H W B %
1254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1256 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
1257 % blackness) triple.
1259 % The format of the ConvertRGBToHWB method is:
1261 % void ConvertRGBToHWB(const double red,const double green,
1262 % const double blue,double *hue,double *whiteness,double *blackness)
1264 % A description of each parameter follows:
1266 % o red, green, blue: A Quantum value representing the red, green, and
1267 % blue component of a pixel.
1269 % o hue, whiteness, blackness: A pointer to a double value representing a
1270 % component of the HWB color space.
1273 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
1274 const double blue,double *hue,double *whiteness,double *blackness)
1286 Convert RGB to HWB colorspace.
1288 assert(hue != (double *) NULL);
1289 assert(whiteness != (double *) NULL);
1290 assert(blackness != (double *) NULL);
1294 w=MagickMin(r,MagickMin(g,b));
1295 v=MagickMax(r,MagickMax(g,b));
1296 *blackness=1.0-QuantumScale*v;
1297 *whiteness=QuantumScale*w;
1303 f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
1304 p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
1305 *hue=(p-f/(v-1.0*w))/6.0;
1309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1313 % C o n v e r t R G B T o L C H a b %
1317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319 % ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
1322 % The format of the ConvertRGBToLCHab method is:
1324 % void ConvertRGBToLCHab(const double red,const double green,
1325 % const double blue,double *luma,double *chroma,double *hue)
1327 % A description of each parameter follows:
1329 % o red, green, blue: A Quantum value representing the red, green, and
1330 % blue component of a pixel.
1332 % o luma, chroma, hue: A pointer to a double value representing a
1333 % component of the LCH color space.
1337 static inline void ConvertXYZToLCHab(const double X,const double Y,
1338 const double Z,double *luma,double *chroma,double *hue)
1344 ConvertXYZToLab(X,Y,Z,luma,&a,&b);
1345 *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5;
1346 *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0+0.5;
1351 MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
1352 const double blue,double *luma,double *chroma,double *hue)
1360 Convert RGB to LCHab colorspace.
1362 assert(luma != (double *) NULL);
1363 assert(chroma != (double *) NULL);
1364 assert(hue != (double *) NULL);
1365 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1366 ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
1370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1374 % C o n v e r t R G B T o L C H u v %
1378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1380 % ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
1383 % The format of the ConvertRGBToLCHuv method is:
1385 % void ConvertRGBToLCHuv(const double red,const double green,
1386 % const double blue,double *luma,double *chroma,double *hue)
1388 % A description of each parameter follows:
1390 % o red, green, blue: A Quantum value representing the red, green, and
1391 % blue component of a pixel.
1393 % o luma, chroma, hue: A pointer to a double value representing a
1394 % component of the LCHuv color space.
1398 static inline void ConvertXYZToLCHuv(const double X,const double Y,
1399 const double Z,double *luma,double *chroma,double *hue)
1405 ConvertXYZToLuv(X,Y,Z,luma,&u,&v);
1406 *chroma=hypot(354.0*u-134.0,262.0*v-140.0)/255.0+0.5;
1407 *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI/360.0+0.5;
1412 MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
1413 const double blue,double *luma,double *chroma,double *hue)
1421 Convert RGB to LCHuv colorspace.
1423 assert(luma != (double *) NULL);
1424 assert(chroma != (double *) NULL);
1425 assert(hue != (double *) NULL);
1426 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1427 ConvertXYZToLCHuv(X,Y,Z,luma,chroma,hue);
1431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435 % E x p a n d A f f i n e %
1439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441 % ExpandAffine() computes the affine's expansion factor, i.e. the square root
1442 % of the factor by which the affine transform affects area. In an affine
1443 % transform composed of scaling, rotation, shearing, and translation, returns
1444 % the amount of scaling.
1446 % The format of the ExpandAffine method is:
1448 % double ExpandAffine(const AffineMatrix *affine)
1450 % A description of each parameter follows:
1452 % o expansion: ExpandAffine returns the affine's expansion factor.
1454 % o affine: A pointer the affine transform of type AffineMatrix.
1457 MagickExport double ExpandAffine(const AffineMatrix *affine)
1459 assert(affine != (const AffineMatrix *) NULL);
1460 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
1464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1468 % G e n e r a t e D i f f e r e n t i a l N o i s e %
1472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474 % GenerateDifferentialNoise() generates differentual noise.
1476 % The format of the GenerateDifferentialNoise method is:
1478 % double GenerateDifferentialNoise(RandomInfo *random_info,
1479 % const Quantum pixel,const NoiseType noise_type,const double attenuate)
1481 % A description of each parameter follows:
1483 % o random_info: the random info.
1485 % o pixel: noise is relative to this pixel value.
1487 % o noise_type: the type of noise.
1489 % o attenuate: attenuate the noise.
1492 MagickPrivate double GenerateDifferentialNoise(RandomInfo *random_info,
1493 const Quantum pixel,const NoiseType noise_type,const double attenuate)
1495 #define SigmaUniform (attenuate*0.015625)
1496 #define SigmaGaussian (attenuate*0.015625)
1497 #define SigmaImpulse (attenuate*0.1)
1498 #define SigmaLaplacian (attenuate*0.0390625)
1499 #define SigmaMultiplicativeGaussian (attenuate*0.5)
1500 #define SigmaPoisson (attenuate*12.5)
1501 #define SigmaRandom (attenuate)
1502 #define TauGaussian (attenuate*0.078125)
1510 alpha=GetPseudoRandomValue(random_info);
1516 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
1527 beta=GetPseudoRandomValue(random_info);
1528 gamma=sqrt(-2.0*log(alpha));
1529 sigma=gamma*cos((double) (2.0*MagickPI*beta));
1530 tau=gamma*sin((double) (2.0*MagickPI*beta));
1531 noise=(double) (pixel+sqrt((double) pixel)*SigmaGaussian*sigma+
1532 QuantumRange*TauGaussian*tau);
1537 if (alpha < (SigmaImpulse/2.0))
1540 if (alpha >= (1.0-(SigmaImpulse/2.0)))
1541 noise=(double) QuantumRange;
1543 noise=(double) pixel;
1546 case LaplacianNoise:
1550 if (alpha <= MagickEpsilon)
1551 noise=(double) (pixel-QuantumRange);
1553 noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
1558 if (beta <= (0.5*MagickEpsilon))
1559 noise=(double) (pixel+QuantumRange);
1561 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
1564 case MultiplicativeGaussianNoise:
1567 if (alpha > MagickEpsilon)
1568 sigma=sqrt(-2.0*log(alpha));
1569 beta=GetPseudoRandomValue(random_info);
1570 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
1571 cos((double) (2.0*MagickPI*beta))/2.0);
1582 poisson=exp(-SigmaPoisson*QuantumScale*pixel);
1583 for (i=0; alpha > poisson; i++)
1585 beta=GetPseudoRandomValue(random_info);
1588 noise=(double) (QuantumRange*i/SigmaPoisson);
1593 noise=(double) (QuantumRange*SigmaRandom*alpha);
1601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605 % G e t O p t i m a l K e r n e l W i d t h %
1609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1611 % GetOptimalKernelWidth() computes the optimal kernel radius for a convolution
1612 % filter. Start with the minimum value of 3 pixels and walk out until we drop
1613 % below the threshold of one pixel numerical accuracy.
1615 % The format of the GetOptimalKernelWidth method is:
1617 % size_t GetOptimalKernelWidth(const double radius,
1618 % const double sigma)
1620 % A description of each parameter follows:
1622 % o width: GetOptimalKernelWidth returns the optimal width of a
1623 % convolution kernel.
1625 % o radius: the radius of the Gaussian, in pixels, not counting the center
1628 % o sigma: the standard deviation of the Gaussian, in pixels.
1631 MagickPrivate size_t GetOptimalKernelWidth1D(const double radius,
1650 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1651 if (radius > MagickEpsilon)
1652 return((size_t) (2.0*ceil(radius)+1.0));
1654 if (gamma <= MagickEpsilon)
1656 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1657 beta=(double) PerceptibleReciprocal((double) MagickSQ2PI*gamma);
1661 j=(ssize_t) (width-1)/2;
1662 for (i=(-j); i <= j; i++)
1663 normalize+=exp(-((double) (i*i))*alpha)*beta;
1664 value=exp(-((double) (j*j))*alpha)*beta/normalize;
1665 if ((value < QuantumScale) || (value < MagickEpsilon))
1669 return((size_t) (width-2));
1672 MagickPrivate size_t GetOptimalKernelWidth2D(const double radius,
1690 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1691 if (radius > MagickEpsilon)
1692 return((size_t) (2.0*ceil(radius)+1.0));
1694 if (gamma <= MagickEpsilon)
1696 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1697 beta=(double) PerceptibleReciprocal((double) Magick2PI*gamma*gamma);
1701 j=(ssize_t) (width-1)/2;
1702 for (v=(-j); v <= j; v++)
1703 for (u=(-j); u <= j; u++)
1704 normalize+=exp(-((double) (u*u+v*v))*alpha)*beta;
1705 value=exp(-((double) (j*j))*alpha)*beta/normalize;
1706 if ((value < QuantumScale) || (value < MagickEpsilon))
1710 return((size_t) (width-2));
1713 MagickPrivate size_t GetOptimalKernelWidth(const double radius,
1716 return(GetOptimalKernelWidth1D(radius,sigma));