43 #include "magick/studio.h"
44 #include "magick/color-private.h"
45 #include "magick/draw.h"
46 #include "magick/gem.h"
47 #include "magick/gem-private.h"
48 #include "magick/image.h"
49 #include "magick/image-private.h"
50 #include "magick/log.h"
51 #include "magick/memory_.h"
52 #include "magick/pixel-private.h"
53 #include "magick/quantum.h"
54 #include "magick/random_.h"
55 #include "magick/resize.h"
56 #include "magick/transform.h"
57 #include "magick/signature-private.h"
86 MagickExport
void ConvertHCLToRGB(
const double hue,
const double chroma,
87 const double luma,Quantum *red,Quantum *green,Quantum *blue)
101 assert(red != (Quantum *) NULL);
102 assert(green != (Quantum *) NULL);
103 assert(blue != (Quantum *) NULL);
106 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
110 if ((0.0 <= h) && (h < 1.0))
116 if ((1.0 <= h) && (h < 2.0))
122 if ((2.0 <= h) && (h < 3.0))
128 if ((3.0 <= h) && (h < 4.0))
134 if ((4.0 <= h) && (h < 5.0))
140 if ((5.0 <= h) && (h < 6.0))
145 m=luma-(0.298839*r+0.586811*g+0.114350*b);
146 *red=ClampToQuantum(QuantumRange*(r+m));
147 *green=ClampToQuantum(QuantumRange*(g+m));
148 *blue=ClampToQuantum(QuantumRange*(b+m));
179 MagickExport
void ConvertHCLpToRGB(
const double hue,
const double chroma,
180 const double luma,Quantum *red,Quantum *green,Quantum *blue)
195 assert(red != (Quantum *) NULL);
196 assert(green != (Quantum *) NULL);
197 assert(blue != (Quantum *) NULL);
200 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
204 if ((0.0 <= h) && (h < 1.0))
210 if ((1.0 <= h) && (h < 2.0))
216 if ((2.0 <= h) && (h < 3.0))
222 if ((3.0 <= h) && (h < 4.0))
228 if ((4.0 <= h) && (h < 5.0))
234 if ((5.0 <= h) && (h < 6.0))
239 m=luma-(0.298839*r+0.586811*g+0.114350*b);
249 z=(1.0-luma)/(m+c-luma);
252 *red=ClampToQuantum(QuantumRange*(z*r+m));
253 *green=ClampToQuantum(QuantumRange*(z*g+m));
254 *blue=ClampToQuantum(QuantumRange*(z*b+m));
284 MagickExport
void ConvertHSBToRGB(
const double hue,
const double saturation,
285 const double brightness,Quantum *red,Quantum *green,Quantum *blue)
297 assert(red != (Quantum *) NULL);
298 assert(green != (Quantum *) NULL);
299 assert(blue != (Quantum *) NULL);
300 if (fabs(saturation) < MagickEpsilon)
302 *red=ClampToQuantum(QuantumRange*brightness);
307 h=6.0*(hue-floor(hue));
308 f=h-floor((
double) h);
309 p=brightness*(1.0-saturation);
310 q=brightness*(1.0-saturation*f);
311 t=brightness*(1.0-(saturation*(1.0-f)));
317 *red=ClampToQuantum(QuantumRange*brightness);
318 *green=ClampToQuantum(QuantumRange*t);
319 *blue=ClampToQuantum(QuantumRange*p);
324 *red=ClampToQuantum(QuantumRange*q);
325 *green=ClampToQuantum(QuantumRange*brightness);
326 *blue=ClampToQuantum(QuantumRange*p);
331 *red=ClampToQuantum(QuantumRange*p);
332 *green=ClampToQuantum(QuantumRange*brightness);
333 *blue=ClampToQuantum(QuantumRange*t);
338 *red=ClampToQuantum(QuantumRange*p);
339 *green=ClampToQuantum(QuantumRange*q);
340 *blue=ClampToQuantum(QuantumRange*brightness);
345 *red=ClampToQuantum(QuantumRange*t);
346 *green=ClampToQuantum(QuantumRange*p);
347 *blue=ClampToQuantum(QuantumRange*brightness);
352 *red=ClampToQuantum(QuantumRange*brightness);
353 *green=ClampToQuantum(QuantumRange*p);
354 *blue=ClampToQuantum(QuantumRange*q);
387 MagickExport
void ConvertHSIToRGB(
const double hue,
const double saturation,
388 const double intensity,Quantum *red,Quantum *green,Quantum *blue)
399 assert(red != (Quantum *) NULL);
400 assert(green != (Quantum *) NULL);
401 assert(blue != (Quantum *) NULL);
403 h-=360.0*floor(h/360.0);
406 b=intensity*(1.0-saturation);
407 r=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
415 r=intensity*(1.0-saturation);
416 g=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
423 g=intensity*(1.0-saturation);
424 b=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
428 *red=ClampToQuantum(QuantumRange*r);
429 *green=ClampToQuantum(QuantumRange*g);
430 *blue=ClampToQuantum(QuantumRange*b);
460 MagickExport
void ConvertHSLToRGB(
const double hue,
const double saturation,
461 const double lightness,Quantum *red,Quantum *green,Quantum *blue)
475 assert(red != (Quantum *) NULL);
476 assert(green != (Quantum *) NULL);
477 assert(blue != (Quantum *) NULL);
479 if (lightness <= 0.5)
480 c=2.0*lightness*saturation;
482 c=(2.0-2.0*lightness)*saturation;
484 h-=360.0*floor(h/360.0);
486 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
487 switch ((
int) floor(h))
538 *red=ClampToQuantum(QuantumRange*r);
539 *green=ClampToQuantum(QuantumRange*g);
540 *blue=ClampToQuantum(QuantumRange*b);
570 MagickExport
void ConvertHSVToRGB(
const double hue,
const double saturation,
571 const double value,Quantum *red,Quantum *green,Quantum *blue)
585 assert(red != (Quantum *) NULL);
586 assert(green != (Quantum *) NULL);
587 assert(blue != (Quantum *) NULL);
591 h-=360.0*floor(h/360.0);
593 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
594 switch ((
int) floor(h))
645 *red=ClampToQuantum(QuantumRange*r);
646 *green=ClampToQuantum(QuantumRange*g);
647 *blue=ClampToQuantum(QuantumRange*b);
677 MagickExport
void ConvertHWBToRGB(
const double hue,
const double whiteness,
678 const double blackness,Quantum *red,Quantum *green,Quantum *blue)
694 assert(red != (Quantum *) NULL);
695 assert(green != (Quantum *) NULL);
696 assert(blue != (Quantum *) NULL);
698 if (fabs(hue-(-1.0)) < MagickEpsilon)
700 *red=ClampToQuantum(QuantumRange*v);
701 *green=ClampToQuantum(QuantumRange*v);
702 *blue=ClampToQuantum(QuantumRange*v);
705 i=CastDoubleToLong(floor(6.0*hue));
709 n=whiteness+f*(v-whiteness);
714 case 0: r=v; g=n; b=whiteness;
break;
715 case 1: r=n; g=v; b=whiteness;
break;
716 case 2: r=whiteness; g=v; b=n;
break;
717 case 3: r=whiteness; g=n; b=v;
break;
718 case 4: r=n; g=whiteness; b=v;
break;
719 case 5: r=v; g=whiteness; b=n;
break;
721 *red=ClampToQuantum(QuantumRange*r);
722 *green=ClampToQuantum(QuantumRange*g);
723 *blue=ClampToQuantum(QuantumRange*b);
754 static inline void ConvertLCHabToXYZ(
const double luma,
const double chroma,
755 const double hue,
double *X,
double *Y,
double *Z)
757 ConvertLabToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
758 sin(hue*MagickPI/180.0),X,Y,Z);
761 MagickExport
void ConvertLCHabToRGB(
const double luma,
const double chroma,
762 const double hue,Quantum *red,Quantum *green,Quantum *blue)
772 assert(red != (Quantum *) NULL);
773 assert(green != (Quantum *) NULL);
774 assert(blue != (Quantum *) NULL);
775 ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
776 ConvertXYZToRGB(X,Y,Z,red,green,blue);
807 static inline void ConvertLCHuvToXYZ(
const double luma,
const double chroma,
808 const double hue,
double *X,
double *Y,
double *Z)
810 ConvertLuvToXYZ(luma,chroma*cos(hue*MagickPI/180.0),chroma*
811 sin(hue*MagickPI/180.0),X,Y,Z);
814 MagickExport
void ConvertLCHuvToRGB(
const double luma,
const double chroma,
815 const double hue,Quantum *red,Quantum *green,Quantum *blue)
825 assert(red != (Quantum *) NULL);
826 assert(green != (Quantum *) NULL);
827 assert(blue != (Quantum *) NULL);
828 ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,&X,&Y,&Z);
829 ConvertXYZToRGB(X,Y,Z,red,green,blue);
860 MagickExport
void ConvertRGBToHCL(
const Quantum red,
const Quantum green,
861 const Quantum blue,
double *hue,
double *chroma,
double *luma)
874 assert(hue != (
double *) NULL);
875 assert(chroma != (
double *) NULL);
876 assert(luma != (
double *) NULL);
880 max=MagickMax(r,MagickMax(g,b));
881 c=max-(double) MagickMin(r,MagickMin(g,b));
883 if (fabs(c) < MagickEpsilon)
886 if (red == (Quantum) max)
887 h=fmod((g-b)/c+6.0,6.0);
889 if (green == (Quantum) max)
892 if (blue == (Quantum) max)
895 *chroma=QuantumScale*c;
896 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
927 MagickExport
void ConvertRGBToHCLp(
const Quantum red,
const Quantum green,
928 const Quantum blue,
double *hue,
double *chroma,
double *luma)
941 assert(hue != (
double *) NULL);
942 assert(chroma != (
double *) NULL);
943 assert(luma != (
double *) NULL);
947 max=MagickMax(r,MagickMax(g,b));
948 c=max-(double) MagickMin(r,MagickMin(g,b));
950 if (fabs(c) < MagickEpsilon)
953 if (red == (Quantum) max)
954 h=fmod((g-b)/c+6.0,6.0);
956 if (green == (Quantum) max)
959 if (blue == (Quantum) max)
962 *chroma=QuantumScale*c;
963 *luma=QuantumScale*(0.298839*r+0.586811*g+0.114350*b);
994 MagickExport
void ConvertRGBToHSB(
const Quantum red,
const Quantum green,
995 const Quantum blue,
double *hue,
double *saturation,
double *brightness)
1008 assert(hue != (
double *) NULL);
1009 assert(saturation != (
double *) NULL);
1010 assert(brightness != (
double *) NULL);
1023 if (fabs(max) < MagickEpsilon)
1026 *saturation=delta/max;
1027 *brightness=QuantumScale*max;
1028 if (fabs(delta) < MagickEpsilon)
1030 if (fabs(r-max) < MagickEpsilon)
1033 if (fabs(g-max) < MagickEpsilon)
1034 *hue=2.0+(b-r)/delta;
1036 *hue=4.0+(r-g)/delta;
1070 MagickExport
void ConvertRGBToHSI(
const Quantum red,
const Quantum green,
1071 const Quantum blue,
double *hue,
double *saturation,
double *intensity)
1080 assert(hue != (
double *) NULL);
1081 assert(saturation != (
double *) NULL);
1082 assert(intensity != (
double *) NULL);
1083 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
1084 if (*intensity <= 0.0)
1090 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1091 QuantumScale*blue))/(*intensity);
1092 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
1093 beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
1094 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
1127 MagickExport
void ConvertRGBToHSL(
const Quantum red,
const Quantum green,
1128 const Quantum blue,
double *hue,
double *saturation,
double *lightness)
1138 assert(hue != (
double *) NULL);
1139 assert(saturation != (
double *) NULL);
1140 assert(lightness != (
double *) NULL);
1141 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1142 QuantumScale*blue));
1143 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1144 QuantumScale*blue));
1146 *lightness=(max+min)/2.0;
1153 if (fabs(max-QuantumScale*red) < MagickEpsilon)
1155 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1156 if ((QuantumScale*green) < (QuantumScale*blue))
1160 if (fabs(max-QuantumScale*green) < MagickEpsilon)
1161 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1163 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1165 if (*lightness <= 0.5)
1166 *saturation=c*PerceptibleReciprocal(2.0*(*lightness));
1168 *saturation=c*PerceptibleReciprocal(2.0-2.0*(*lightness));
1199 MagickExport
void ConvertRGBToHSV(
const Quantum red,
const Quantum green,
1200 const Quantum blue,
double *hue,
double *saturation,
double *value)
1210 assert(hue != (
double *) NULL);
1211 assert(saturation != (
double *) NULL);
1212 assert(value != (
double *) NULL);
1213 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1214 QuantumScale*blue));
1215 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1216 QuantumScale*blue));
1225 if (fabs(max-QuantumScale*red) < MagickEpsilon)
1227 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1228 if ((QuantumScale*green) < (QuantumScale*blue))
1232 if (fabs(max-QuantumScale*green) < MagickEpsilon)
1233 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1235 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1237 *saturation=c*PerceptibleReciprocal(max);
1268 MagickExport
void ConvertRGBToHWB(
const Quantum red,
const Quantum green,
1269 const Quantum blue,
double *hue,
double *whiteness,
double *blackness)
1283 assert(hue != (
double *) NULL);
1284 assert(whiteness != (
double *) NULL);
1285 assert(blackness != (
double *) NULL);
1289 w=MagickMin(r,MagickMin(g,b));
1290 v=MagickMax(r,MagickMax(g,b));
1291 *blackness=1.0-QuantumScale*v;
1292 *whiteness=QuantumScale*w;
1293 if (fabs(v-w) < MagickEpsilon)
1298 f=(fabs(r-w) < MagickEpsilon) ? g-b : ((fabs(g-w) < MagickEpsilon) ? b-r : r-g);
1299 p=(fabs(r-w) < MagickEpsilon) ? 3.0 : ((fabs(g-w) < MagickEpsilon) ? 5.0 : 1.0);
1300 *hue=(p-f/(v-1.0*w))/6.0;
1331 static inline void ConvertXYZToLCHab(
const double X,
const double Y,
1332 const double Z,
double *luma,
double *chroma,
double *hue)
1338 ConvertXYZToLab(X,Y,Z,luma,&a,&b);
1339 *chroma=hypot(255.0*(a-0.5),255.0*(b-0.5))/255.0+0.5;
1340 *hue=180.0*atan2(255.0*(b-0.5),255.0*(a-0.5))/MagickPI/360.0;
1345 MagickExport
void ConvertRGBToLCHab(
const Quantum red,
const Quantum green,
1346 const Quantum blue,
double *luma,
double *chroma,
double *hue)
1356 assert(luma != (
double *) NULL);
1357 assert(chroma != (
double *) NULL);
1358 assert(hue != (
double *) NULL);
1359 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1360 ConvertXYZToLCHab(X,Y,Z,luma,chroma,hue);
1392 static inline void ConvertXYZToLCHuv(
const double X,
const double Y,
1393 const double Z,
double *luma,
double *chroma,
double *hue)
1399 ConvertXYZToLuv(X,Y,Z,luma,&u,&v);
1400 *chroma=hypot(354.0*u-134.0,262.0*v-140.0)/255.0+0.5;
1401 *hue=180.0*atan2(262.0*v-140.0,354.0*u-134.0)/MagickPI/360.0;
1406 MagickExport
void ConvertRGBToLCHuv(
const Quantum red,
const Quantum green,
1407 const Quantum blue,
double *luma,
double *chroma,
double *hue)
1417 assert(luma != (
double *) NULL);
1418 assert(chroma != (
double *) NULL);
1419 assert(hue != (
double *) NULL);
1420 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1421 ConvertXYZToLCHuv(X,Y,Z,luma,chroma,hue);
1451 MagickExport
double ExpandAffine(
const AffineMatrix *affine)
1454 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
1487 MagickExport
double GenerateDifferentialNoise(
RandomInfo *random_info,
1488 const Quantum pixel,
const NoiseType noise_type,
const MagickRealType attenuate)
1490 #define SigmaUniform (attenuate*0.015625)
1491 #define SigmaGaussian (attenuate*0.015625)
1492 #define SigmaImpulse (attenuate*0.1)
1493 #define SigmaLaplacian (attenuate*0.0390625)
1494 #define SigmaMultiplicativeGaussian (attenuate*0.5)
1495 #define SigmaPoisson (attenuate*12.5)
1496 #define SigmaRandom (attenuate)
1497 #define TauGaussian (attenuate*0.078125)
1505 alpha=GetPseudoRandomValue(random_info);
1511 noise=(double) (pixel+QuantumRange*SigmaUniform*(alpha-0.5));
1520 if (fabs(alpha) < MagickEpsilon)
1522 beta=GetPseudoRandomValue(random_info);
1523 gamma=sqrt(-2.0*log(alpha));
1524 sigma=gamma*cos((
double) (2.0*MagickPI*beta));
1525 tau=gamma*sin((
double) (2.0*MagickPI*beta));
1526 noise=(double) (pixel+sqrt((
double) pixel)*SigmaGaussian*sigma+
1527 QuantumRange*TauGaussian*tau);
1532 if (alpha < (SigmaImpulse/2.0))
1535 if (alpha >= (1.0-(SigmaImpulse/2.0)))
1536 noise=(
double) QuantumRange;
1538 noise=(double) pixel;
1541 case LaplacianNoise:
1545 if (alpha <= MagickEpsilon)
1546 noise=(double) (pixel-QuantumRange);
1548 noise=(double) (pixel+QuantumRange*SigmaLaplacian*log(2.0*alpha)+
1553 if (beta <= (0.5*MagickEpsilon))
1554 noise=(
double) (pixel+QuantumRange);
1556 noise=(double) (pixel-QuantumRange*SigmaLaplacian*log(2.0*beta)+0.5);
1559 case MultiplicativeGaussianNoise:
1562 if (alpha > MagickEpsilon)
1563 sigma=sqrt(-2.0*log(alpha));
1564 beta=GetPseudoRandomValue(random_info);
1565 noise=(double) (pixel+pixel*SigmaMultiplicativeGaussian*sigma*
1566 cos((
double) (2.0*MagickPI*beta))/2.0);
1577 poisson=exp(-SigmaPoisson*QuantumScale*pixel);
1578 for (i=0; alpha > poisson; i++)
1580 beta=GetPseudoRandomValue(random_info);
1583 noise=(double) (QuantumRange*i*PerceptibleReciprocal(SigmaPoisson));
1588 noise=(double) (QuantumRange*SigmaRandom*alpha);
1622 MagickExport
size_t GetOptimalKernelWidth1D(
const double radius,
1639 if (IsEventLogging() != MagickFalse)
1640 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1641 if (radius > MagickEpsilon)
1642 return((
size_t) (2.0*ceil(radius)+1.0));
1644 if (gamma <= MagickEpsilon)
1646 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1647 beta=(double) PerceptibleReciprocal((
double) MagickSQ2PI*gamma);
1651 j=(ssize_t) (width-1)/2;
1652 for (i=(-j); i <= j; i++)
1653 normalize+=exp(-((
double) (i*i))*alpha)*beta;
1654 value=exp(-((
double) (j*j))*alpha)*beta/normalize;
1655 if ((value < QuantumScale) || (value < MagickEpsilon))
1659 return((
size_t) (width-2));
1662 MagickExport
size_t GetOptimalKernelWidth2D(
const double radius,
1680 if (IsEventLogging() != MagickFalse)
1681 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1682 if (radius > MagickEpsilon)
1683 return((
size_t) (2.0*ceil(radius)+1.0));
1685 if (gamma <= MagickEpsilon)
1687 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1688 beta=(double) PerceptibleReciprocal((
double) Magick2PI*gamma*gamma);
1692 j=(ssize_t) (width-1)/2;
1693 for (v=(-j); v <= j; v++)
1694 for (u=(-j); u <= j; u++)
1695 normalize+=exp(-((
double) (u*u+v*v))*alpha)*beta;
1696 value=exp(-((
double) (j*j))*alpha)*beta/normalize;
1697 if ((value < QuantumScale) || (value < MagickEpsilon))
1701 return((
size_t) (width-2));
1704 MagickExport
size_t GetOptimalKernelWidth(
const double radius,
1707 return(GetOptimalKernelWidth1D(radius,sigma));