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)
396 Convert HSI to RGB colorspace.
398 assert(red != (double *) NULL);
399 assert(green != (double *) NULL);
400 assert(blue != (double *) NULL);
402 h-=360.0*floor(h/360.0);
405 *blue=intensity*(1.0-saturation);
406 *red=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
408 *green=3.0*intensity-*red-*blue;
414 *red=intensity*(1.0-saturation);
415 *green=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
417 *blue=3.0*intensity-*red-*green;
422 *green=intensity*(1.0-saturation);
423 *blue=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
425 *red=3.0*intensity-*green-*blue;
428 *green*=QuantumRange;
433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 % C o n v e r t H S L T o R G B %
441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 % ConvertHSLToRGB() transforms a (hue, saturation, lightness) to a (red,
444 % green, blue) triple.
446 % The format of the ConvertHSLToRGBImage method is:
448 % void ConvertHSLToRGB(const double hue,const double saturation,
449 % const double lightness,double *red,double *green,double *blue)
451 % A description of each parameter follows:
453 % o hue, saturation, lightness: A double value representing a
454 % component of the HSL color space.
456 % o red, green, blue: A pointer to a pixel component of type Quantum.
459 MagickExport void ConvertHSLToRGB(const double hue,const double saturation,
460 const double lightness,double *red,double *green,double *blue)
469 Convert HSL to RGB colorspace.
471 assert(red != (double *) NULL);
472 assert(green != (double *) NULL);
473 assert(blue != (double *) NULL);
475 if (lightness <= 0.5)
476 c=2.0*lightness*saturation;
478 c=(2.0-2.0*lightness)*saturation;
480 h-=360.0*floor(h/360.0);
482 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
483 switch ((int) floor(h))
487 *red=QuantumRange*(min+c);
488 *green=QuantumRange*(min+x);
489 *blue=QuantumRange*min;
494 *red=QuantumRange*(min+x);
495 *green=QuantumRange*(min+c);
496 *blue=QuantumRange*min;
501 *red=QuantumRange*min;
502 *green=QuantumRange*(min+c);
503 *blue=QuantumRange*(min+x);
508 *red=QuantumRange*min;
509 *green=QuantumRange*(min+x);
510 *blue=QuantumRange*(min+c);
515 *red=QuantumRange*(min+x);
516 *green=QuantumRange*min;
517 *blue=QuantumRange*(min+c);
522 *red=QuantumRange*(min+c);
523 *green=QuantumRange*min;
524 *blue=QuantumRange*(min+x);
537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541 % C o n v e r t H S V T o R G B %
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 % ConvertHSVToRGB() transforms a (hue, saturation, value) to a (red,
548 % green, blue) triple.
550 % The format of the ConvertHSVToRGBImage method is:
552 % void ConvertHSVToRGB(const double hue,const double saturation,
553 % const double value,double *red,double *green,double *blue)
555 % A description of each parameter follows:
557 % o hue, saturation, value: A double value representing a
558 % component of the HSV color space.
560 % o red, green, blue: A pointer to a pixel component of type Quantum.
563 MagickPrivate void ConvertHSVToRGB(const double hue,const double saturation,
564 const double value,double *red,double *green,double *blue)
573 Convert HSV to RGB colorspace.
575 assert(red != (double *) NULL);
576 assert(green != (double *) NULL);
577 assert(blue != (double *) NULL);
581 h-=360.0*floor(h/360.0);
583 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
584 switch ((int) floor(h))
588 *red=QuantumRange*(min+c);
589 *green=QuantumRange*(min+x);
590 *blue=QuantumRange*min;
595 *red=QuantumRange*(min+x);
596 *green=QuantumRange*(min+c);
597 *blue=QuantumRange*min;
602 *red=QuantumRange*min;
603 *green=QuantumRange*(min+c);
604 *blue=QuantumRange*(min+x);
609 *red=QuantumRange*min;
610 *green=QuantumRange*(min+x);
611 *blue=QuantumRange*(min+c);
616 *red=QuantumRange*(min+x);
617 *green=QuantumRange*min;
618 *blue=QuantumRange*(min+c);
623 *red=QuantumRange*(min+c);
624 *green=QuantumRange*min;
625 *blue=QuantumRange*(min+x);
638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642 % C o n v e r t H W B T o R G B %
646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648 % ConvertHWBToRGB() transforms a (hue, whiteness, blackness) to a (red, green,
651 % The format of the ConvertHWBToRGBImage method is:
653 % void ConvertHWBToRGB(const double hue,const double whiteness,
654 % const double blackness,double *red,double *green,double *blue)
656 % A description of each parameter follows:
658 % o hue, whiteness, blackness: A double value representing a
659 % component of the HWB color space.
661 % o red, green, blue: A pointer to a pixel component of type Quantum.
664 MagickPrivate void ConvertHWBToRGB(const double hue,const double whiteness,
665 const double blackness,double *red,double *green,double *blue)
679 Convert HWB to RGB colorspace.
681 assert(red != (double *) NULL);
682 assert(green != (double *) NULL);
683 assert(blue != (double *) NULL);
688 *green=QuantumRange*v;
689 *blue=QuantumRange*v;
692 i=(ssize_t) floor(6.0*hue);
696 n=whiteness+f*(v-whiteness); /* linear interpolation */
701 case 0: r=v; g=n; b=whiteness; break;
702 case 1: r=n; g=v; b=whiteness; break;
703 case 2: r=whiteness; g=v; b=n; break;
704 case 3: r=whiteness; g=n; b=v; break;
705 case 4: r=n; g=whiteness; b=v; break;
706 case 5: r=v; g=whiteness; b=n; break;
709 *green=QuantumRange*g;
710 *blue=QuantumRange*b;
714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718 % C o n v e r t L C H a b T o R G B %
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 % ConvertLCHabToRGB() transforms a (luma, chroma, hue) to a (red, green,
727 % The format of the ConvertLCHabToRGBImage method is:
729 % void ConvertLCHabToRGB(const double luma,const double chroma,
730 % const double hue,double *red,double *green,double *blue)
732 % A description of each parameter follows:
734 % o luma, chroma, hue: A double value representing a component of the
737 % o red, green, blue: A pointer to a pixel component of type Quantum.
740 MagickPrivate void ConvertLCHabToRGB(const double luma,const double chroma,
741 const double hue,double *red,double *green,double *blue)
754 Convert LCHab to RGB colorspace.
756 assert(red != (double *) NULL);
757 assert(green != (double *) NULL);
758 assert(blue != (double *) NULL);
762 a=C*cos(360.0*H*MagickPI/180.0);
763 b=C*sin(360.0*H*MagickPI/180.0);
764 ConvertLabToXYZ(((116.0*L)-16.0)/100.0,(500.0*a)/255.0+0.5,(200.0*b)/255.0+
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.
796 MagickPrivate void ConvertLCHuvToRGB(const double luma,const double chroma,
797 const double hue,double *red,double *green,double *blue)
810 Convert LCHuv to RGB colorspace.
812 assert(red != (double *) NULL);
813 assert(green != (double *) NULL);
814 assert(blue != (double *) NULL);
818 u=C*cos(360.0*H*MagickPI/180.0);
819 v=C*sin(360.0*H*MagickPI/180.0);
820 ConvertLuvToXYZ(L,(u+1.34)/3.54,(v+1.4)/2.62,&X,&Y,&Z);
821 ConvertXYZToRGB(X,Y,Z,red,green,blue);
825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 % C o n v e r t R G B T o H C L %
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835 % ConvertRGBToHCL() transforms a (red, green, blue) to a (hue, chroma,
838 % The format of the ConvertRGBToHCL method is:
840 % void ConvertRGBToHCL(const double red,const double green,
841 % const double blue,double *hue,double *chroma,double *luma)
843 % A description of each parameter follows:
845 % o red, green, blue: A Quantum value representing the red, green, and
846 % blue component of a pixel.
848 % o hue, chroma, luma: A pointer to a double value representing a
849 % component of the HCL color space.
853 static inline double MagickMax(const double x,const double y)
860 static inline double MagickMin(const double x,const double y)
867 MagickPrivate void ConvertRGBToHCL(const double red,const double green,
868 const double blue,double *hue,double *chroma,double *luma)
879 Convert RGB to HCL colorspace.
881 assert(hue != (double *) NULL);
882 assert(chroma != (double *) NULL);
883 assert(luma != (double *) NULL);
887 max=MagickMax(r,MagickMax(g,b));
888 c=max-(double) MagickMin(r,MagickMin(g,b));
894 h=fmod((g-b)/c+6.0,6.0);
902 *chroma=QuantumScale*c;
903 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
911 % C o n v e r t R G B T o H C L p %
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917 % ConvertRGBToHCLp() transforms a (red, green, blue) to a (hue, chroma,
920 % The format of the ConvertRGBToHCLp method is:
922 % void ConvertRGBToHCLp(const double red,const double green,
923 % const double blue,double *hue,double *chroma,double *luma)
925 % A description of each parameter follows:
927 % o red, green, blue: A Quantum value representing the red, green, and
928 % blue component of a pixel.
930 % o hue, chroma, luma: A pointer to a double value representing a
931 % component of the HCL color space.
934 MagickPrivate void ConvertRGBToHCLp(const double red,const double green,
935 const double blue,double *hue,double *chroma,double *luma)
946 Convert RGB to HCL colorspace.
948 assert(hue != (double *) NULL);
949 assert(chroma != (double *) NULL);
950 assert(luma != (double *) NULL);
954 max=MagickMax(r,MagickMax(g,b));
955 c=max-(double) MagickMin(r,MagickMin(g,b));
961 h=fmod((g-b)/c+6.0,6.0);
969 *chroma=QuantumScale*c;
970 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 % C o n v e r t R G B T o H S B %
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984 % ConvertRGBToHSB() transforms a (red, green, blue) to a (hue, saturation,
985 % brightness) triple.
987 % The format of the ConvertRGBToHSB method is:
989 % void ConvertRGBToHSB(const double red,const double green,
990 % const double blue,double *hue,double *saturation,double *brightness)
992 % A description of each parameter follows:
994 % o red, green, blue: A Quantum value representing the red, green, and
995 % blue component of a pixel..
997 % o hue, saturation, brightness: A pointer to a double value representing a
998 % component of the HSB color space.
1001 MagickPrivate void ConvertRGBToHSB(const double red,const double green,
1002 const double blue,double *hue,double *saturation,double *brightness)
1013 Convert RGB to HSB colorspace.
1015 assert(hue != (double *) NULL);
1016 assert(saturation != (double *) NULL);
1017 assert(brightness != (double *) NULL);
1033 *saturation=delta/max;
1034 *brightness=QuantumScale*max;
1041 *hue=2.0+(b-r)/delta;
1043 *hue=4.0+(r-g)/delta;
1050 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054 % C o n v e r t R G B T o H S I %
1058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1060 % ConvertRGBToHSI() transforms a (red, green, blue) to a (hue, saturation,
1061 % intensity) triple.
1063 % The format of the ConvertRGBToHSI method is:
1065 % void ConvertRGBToHSI(const double red,const double green,
1066 % const double blue,double *hue,double *saturation,double *intensity)
1068 % A description of each parameter follows:
1070 % o red, green, blue: A Quantum value representing the red, green, and
1071 % blue component of a pixel..
1073 % o hue, saturation, intensity: A pointer to a double value representing a
1074 % component of the HSI color space.
1077 MagickPrivate void ConvertRGBToHSI(const double red,const double green,
1078 const double blue,double *hue,double *saturation,double *intensity)
1085 Convert RGB to HSI colorspace.
1087 assert(hue != (double *) NULL);
1088 assert(saturation != (double *) NULL);
1089 assert(intensity != (double *) NULL);
1090 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
1091 if (*intensity <= 0.0)
1097 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1098 QuantumScale*blue))/(*intensity);
1099 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
1100 beta=0.866025403784439*(QuantumScale*green-QuantumScale*blue);
1101 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
1107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 % C o n v e r t R G B T o H S L %
1115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 % ConvertRGBToHSL() transforms a (red, green, blue) to a (hue, saturation,
1118 % lightness) triple.
1120 % The format of the ConvertRGBToHSL method is:
1122 % void ConvertRGBToHSL(const double red,const double green,
1123 % const double blue,double *hue,double *saturation,double *lightness)
1125 % A description of each parameter follows:
1127 % o red, green, blue: A Quantum value representing the red, green, and
1128 % blue component of a pixel..
1130 % o hue, saturation, lightness: A pointer to a double value representing a
1131 % component of the HSL color space.
1134 MagickExport void ConvertRGBToHSL(const double red,const double green,
1135 const double blue,double *hue,double *saturation,double *lightness)
1143 Convert RGB to HSL colorspace.
1145 assert(hue != (double *) NULL);
1146 assert(saturation != (double *) NULL);
1147 assert(lightness != (double *) NULL);
1148 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1149 QuantumScale*blue));
1150 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1151 QuantumScale*blue));
1153 *lightness=(max+min)/2.0;
1160 if (max == (QuantumScale*red))
1162 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1163 if ((QuantumScale*green) < (QuantumScale*blue))
1167 if (max == (QuantumScale*green))
1168 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1170 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1172 if (*lightness <= 0.5)
1173 *saturation=c/(2.0*(*lightness));
1175 *saturation=c/(2.0-2.0*(*lightness));
1179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 % C o n v e r t R G B T o H S V %
1187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189 % ConvertRGBToHSV() transforms a (red, green, blue) to a (hue, saturation,
1192 % The format of the ConvertRGBToHSV method is:
1194 % void ConvertRGBToHSV(const double red,const double green,
1195 % const double blue,double *hue,double *saturation,double *value)
1197 % A description of each parameter follows:
1199 % o red, green, blue: A Quantum value representing the red, green, and
1200 % blue component of a pixel..
1202 % o hue, saturation, value: A pointer to a double value representing a
1203 % component of the HSV color space.
1206 MagickPrivate void ConvertRGBToHSV(const double red,const double green,
1207 const double blue,double *hue,double *saturation,double *value)
1215 Convert RGB to HSV colorspace.
1217 assert(hue != (double *) NULL);
1218 assert(saturation != (double *) NULL);
1219 assert(value != (double *) NULL);
1220 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1221 QuantumScale*blue));
1222 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1223 QuantumScale*blue));
1232 if (max == (QuantumScale*red))
1234 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1235 if ((QuantumScale*green) < (QuantumScale*blue))
1239 if (max == (QuantumScale*green))
1240 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1242 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252 % C o n v e r t R G B T o H W B %
1256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258 % ConvertRGBToHWB() transforms a (red, green, blue) to a (hue, whiteness,
1259 % blackness) triple.
1261 % The format of the ConvertRGBToHWB method is:
1263 % void ConvertRGBToHWB(const double red,const double green,
1264 % const double blue,double *hue,double *whiteness,double *blackness)
1266 % A description of each parameter follows:
1268 % o red, green, blue: A Quantum value representing the red, green, and
1269 % blue component of a pixel.
1271 % o hue, whiteness, blackness: A pointer to a double value representing a
1272 % component of the HWB color space.
1275 MagickPrivate void ConvertRGBToHWB(const double red,const double green,
1276 const double blue,double *hue,double *whiteness,double *blackness)
1288 Convert RGB to HWB colorspace.
1290 assert(hue != (double *) NULL);
1291 assert(whiteness != (double *) NULL);
1292 assert(blackness != (double *) NULL);
1296 w=MagickMin(r,MagickMin(g,b));
1297 v=MagickMax(r,MagickMax(g,b));
1298 *blackness=1.0-QuantumScale*v;
1299 *whiteness=QuantumScale*w;
1305 f=(r == w) ? g-b : ((g == w) ? b-r : r-g);
1306 p=(r == w) ? 3.0 : ((g == w) ? 5.0 : 1.0);
1307 *hue=(p-f/(v-1.0*w))/6.0;
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1315 % C o n v e r t R G B T o L C H a b %
1319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1321 % ConvertRGBToLCHab() transforms a (red, green, blue) to a (luma, chroma,
1324 % The format of the ConvertRGBToLCHab method is:
1326 % void ConvertRGBToLCHab(const double red,const double green,
1327 % const double blue,double *luma,double *chroma,double *hue)
1329 % A description of each parameter follows:
1331 % o red, green, blue: A Quantum value representing the red, green, and
1332 % blue component of a pixel.
1334 % o luma, chroma, hue: A pointer to a double value representing a
1335 % component of the LCH color space.
1338 MagickPrivate void ConvertRGBToLCHab(const double red,const double green,
1339 const double blue,double *luma,double *chroma,double *hue)
1352 Convert RGB to LCHab colorspace.
1354 assert(luma != (double *) NULL);
1355 assert(chroma != (double *) NULL);
1356 assert(hue != (double *) NULL);
1357 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1358 ConvertXYZToLab(X,Y,Z,&L,&a,&b);
1359 C=hypot(255.0*(a-0.5)/500.0,255.0*(b-0.5)/200.0);
1360 H=180.0*atan2(255.0*(b-0.5)/200.0,255.0*(a-0.5)/500.0)/MagickPI/360.0;
1365 *luma=(100.0*L+16.0)/116.0;
1371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1375 % C o n v e r t R G B T o L C H u v %
1379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381 % ConvertRGBToLCHuv() transforms a (red, green, blue) to a (luma, chroma,
1384 % The format of the ConvertRGBToLCHuv method is:
1386 % void ConvertRGBToLCHuv(const double red,const double green,
1387 % const double blue,double *luma,double *chroma,double *hue)
1389 % A description of each parameter follows:
1391 % o red, green, blue: A Quantum value representing the red, green, and
1392 % blue component of a pixel.
1394 % o luma, chroma, hue: A pointer to a double value representing a
1395 % component of the LCHuv color space.
1398 MagickPrivate void ConvertRGBToLCHuv(const double red,const double green,
1399 const double blue,double *luma,double *chroma,double *hue)
1412 Convert RGB to LCHuv colorspace.
1414 assert(luma != (double *) NULL);
1415 assert(chroma != (double *) NULL);
1416 assert(hue != (double *) NULL);
1417 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1418 ConvertXYZToLuv(X,Y,Z,&L,&u,&v);
1419 C=hypot(3.54*u-1.34,2.62*v-1.4);
1420 H=180.0*atan2(2.62*v-1.4,3.54*u-1.34)/MagickPI/360.0;
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));