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/quantum.h"
54#include "MagickCore/quantum-private.h"
55#include "MagickCore/random_.h"
56#include "MagickCore/resize.h"
57#include "MagickCore/transform.h"
58#include "MagickCore/signature-private.h"
87MagickPrivate
void ConvertHCLToRGB(
const double hue,
const double chroma,
88 const double luma,
double *red,
double *green,
double *blue)
102 assert(red != (
double *) NULL);
103 assert(green != (
double *) NULL);
104 assert(blue != (
double *) NULL);
107 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
111 if ((0.0 <= h) && (h < 1.0))
117 if ((1.0 <= h) && (h < 2.0))
123 if ((2.0 <= h) && (h < 3.0))
129 if ((3.0 <= h) && (h < 4.0))
135 if ((4.0 <= h) && (h < 5.0))
141 if ((5.0 <= h) && (h < 6.0))
146 m=luma-(0.298839*r+0.586811*g+0.114350*b);
147 *red=(double) QuantumRange*(r+m);
148 *green=(double) QuantumRange*(g+m);
149 *blue=(double) QuantumRange*(b+m);
180MagickPrivate
void ConvertHCLpToRGB(
const double hue,
const double chroma,
181 const double luma,
double *red,
double *green,
double *blue)
196 assert(red != (
double *) NULL);
197 assert(green != (
double *) NULL);
198 assert(blue != (
double *) NULL);
201 x=c*(1.0-fabs(fmod(h,2.0)-1.0));
205 if ((0.0 <= h) && (h < 1.0))
211 if ((1.0 <= h) && (h < 2.0))
217 if ((2.0 <= h) && (h < 3.0))
223 if ((3.0 <= h) && (h < 4.0))
229 if ((4.0 <= h) && (h < 5.0))
235 if ((5.0 <= h) && (h < 6.0))
240 m=luma-(0.298839*r+0.586811*g+0.114350*b);
250 z=(1.0-luma)/(m+c-luma);
253 *red=(double) QuantumRange*(z*r+m);
254 *green=(double) QuantumRange*(z*g+m);
255 *blue=(double) QuantumRange*(z*b+m);
285MagickPrivate
void ConvertHSBToRGB(
const double hue,
const double saturation,
286 const double brightness,
double *red,
double *green,
double *blue)
298 assert(red != (
double *) NULL);
299 assert(green != (
double *) NULL);
300 assert(blue != (
double *) NULL);
301 if (fabs(saturation) < MagickEpsilon)
303 *red=(double) QuantumRange*brightness;
308 h=6.0*(hue-floor(hue));
309 f=h-floor((
double) h);
310 p=brightness*(1.0-saturation);
311 q=brightness*(1.0-saturation*f);
312 t=brightness*(1.0-(saturation*(1.0-f)));
318 *red=(double) QuantumRange*brightness;
319 *green=(double) QuantumRange*t;
320 *blue=(double) QuantumRange*p;
325 *red=(double) QuantumRange*q;
326 *green=(double) QuantumRange*brightness;
327 *blue=(double) QuantumRange*p;
332 *red=(double) QuantumRange*p;
333 *green=(double) QuantumRange*brightness;
334 *blue=(double) QuantumRange*t;
339 *red=(double) QuantumRange*p;
340 *green=(double) QuantumRange*q;
341 *blue=(double) QuantumRange*brightness;
346 *red=(double) QuantumRange*t;
347 *green=(double) QuantumRange*p;
348 *blue=(double) QuantumRange*brightness;
353 *red=(double) QuantumRange*brightness;
354 *green=(double) QuantumRange*p;
355 *blue=(double) QuantumRange*q;
388MagickPrivate
void ConvertHSIToRGB(
const double hue,
const double saturation,
389 const double intensity,
double *red,
double *green,
double *blue)
400 assert(red != (
double *) NULL);
401 assert(green != (
double *) NULL);
402 assert(blue != (
double *) NULL);
404 h-=360.0*floor(h/360.0);
407 b=intensity*(1.0-saturation);
408 r=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
416 r=intensity*(1.0-saturation);
417 g=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
424 g=intensity*(1.0-saturation);
425 b=intensity*(1.0+saturation*cos(h*(MagickPI/180.0))/cos((60.0-h)*
429 *red=(double) QuantumRange*r;
430 *green=(double) QuantumRange*g;
431 *blue=(double) QuantumRange*b;
461MagickExport
void ConvertHSLToRGB(
const double hue,
const double saturation,
462 const double lightness,
double *red,
double *green,
double *blue)
473 assert(red != (
double *) NULL);
474 assert(green != (
double *) NULL);
475 assert(blue != (
double *) NULL);
477 if (lightness <= 0.5)
478 c=2.0*lightness*saturation;
480 c=(2.0-2.0*lightness)*saturation;
482 h-=360.0*floor(h/360.0);
484 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
485 switch ((
int) floor(h))
490 *red=(double) QuantumRange*(min+c);
491 *green=(double) QuantumRange*(min+x);
492 *blue=(double) QuantumRange*min;
497 *red=(double) QuantumRange*(min+x);
498 *green=(double) QuantumRange*(min+c);
499 *blue=(double) QuantumRange*min;
504 *red=(double) QuantumRange*min;
505 *green=(double) QuantumRange*(min+c);
506 *blue=(double) QuantumRange*(min+x);
511 *red=(double) QuantumRange*min;
512 *green=(double) QuantumRange*(min+x);
513 *blue=(double) QuantumRange*(min+c);
518 *red=(double) QuantumRange*(min+x);
519 *green=(double) QuantumRange*min;
520 *blue=(double) QuantumRange*(min+c);
525 *red=(double) QuantumRange*(min+c);
526 *green=(double) QuantumRange*min;
527 *blue=(double) QuantumRange*(min+x);
560MagickPrivate
void ConvertHSVToRGB(
const double hue,
const double saturation,
561 const double value,
double *red,
double *green,
double *blue)
572 assert(red != (
double *) NULL);
573 assert(green != (
double *) NULL);
574 assert(blue != (
double *) NULL);
578 h-=360.0*floor(h/360.0);
580 x=c*(1.0-fabs(h-2.0*floor(h/2.0)-1.0));
581 switch ((
int) floor(h))
586 *red=(double) QuantumRange*(min+c);
587 *green=(double) QuantumRange*(min+x);
588 *blue=(double) QuantumRange*min;
593 *red=(double) QuantumRange*(min+x);
594 *green=(double) QuantumRange*(min+c);
595 *blue=(double) QuantumRange*min;
600 *red=(double) QuantumRange*min;
601 *green=(double) QuantumRange*(min+c);
602 *blue=(double) QuantumRange*(min+x);
607 *red=(double) QuantumRange*min;
608 *green=(double) QuantumRange*(min+x);
609 *blue=(double) QuantumRange*(min+c);
614 *red=(double) QuantumRange*(min+x);
615 *green=(double) QuantumRange*min;
616 *blue=(double) QuantumRange*(min+c);
621 *red=(double) QuantumRange*(min+c);
622 *green=(double) QuantumRange*min;
623 *blue=(double) QuantumRange*(min+x);
656MagickPrivate
void ConvertHWBToRGB(
const double hue,
const double whiteness,
657 const double blackness,
double *red,
double *green,
double *blue)
673 assert(red != (
double *) NULL);
674 assert(green != (
double *) NULL);
675 assert(blue != (
double *) NULL);
677 if (fabs(hue-(-1.0)) < MagickEpsilon)
679 *red=(double) QuantumRange*v;
680 *green=(double) QuantumRange*v;
681 *blue=(double) QuantumRange*v;
684 i=CastDoubleToLong(floor(6.0*hue));
688 n=whiteness+f*(v-whiteness);
692 default: r=v; g=n; b=whiteness;
break;
693 case 1: r=n; g=v; b=whiteness;
break;
694 case 2: r=whiteness; g=v; b=n;
break;
695 case 3: r=whiteness; g=n; b=v;
break;
696 case 4: r=n; g=whiteness; b=v;
break;
697 case 5: r=v; g=whiteness; b=n;
break;
699 *red=(double) QuantumRange*r;
700 *green=(double) QuantumRange*g;
701 *blue=(double) QuantumRange*b;
732static inline void ConvertLCHabToXYZ(
const double luma,
const double chroma,
733 const double hue,
const IlluminantType illuminant,
double *X,
double *Y,
736 ConvertLabToXYZ(luma,chroma*cos(DegreesToRadians(hue)),chroma*
737 sin(DegreesToRadians(hue)),illuminant,X,Y,Z);
740MagickPrivate
void ConvertLCHabToRGB(
const double luma,
const double chroma,
741 const double hue,
const IlluminantType illuminant,
double *red,
double *green,
752 assert(red != (
double *) NULL);
753 assert(green != (
double *) NULL);
754 assert(blue != (
double *) NULL);
755 ConvertLCHabToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,illuminant,
757 ConvertXYZToRGB(X,Y,Z,red,green,blue);
788static inline void ConvertLCHuvToXYZ(
const double luma,
const double chroma,
789 const double hue,
const IlluminantType illuminant,
double *X,
double *Y,
792 ConvertLuvToXYZ(luma,chroma*cos(DegreesToRadians(hue)),chroma*
793 sin(DegreesToRadians(hue)),illuminant,X,Y,Z);
796MagickPrivate
void ConvertLCHuvToRGB(
const double luma,
const double chroma,
797 const double hue,
const IlluminantType illuminant,
double *red,
double *green,
808 assert(red != (
double *) NULL);
809 assert(green != (
double *) NULL);
810 assert(blue != (
double *) NULL);
811 ConvertLCHuvToXYZ(100.0*luma,255.0*(chroma-0.5),360.0*hue,illuminant,
813 ConvertXYZToRGB(X,Y,Z,red,green,blue);
844MagickPrivate
void ConvertRGBToHCL(
const double red,
const double green,
845 const double blue,
double *hue,
double *chroma,
double *luma)
855 assert(hue != (
double *) NULL);
856 assert(chroma != (
double *) NULL);
857 assert(luma != (
double *) NULL);
858 max=MagickMax(red,MagickMax(green,blue));
859 c=max-(double) MagickMin(red,MagickMin(green,blue));
861 if (fabs(c) < MagickEpsilon)
864 if (fabs(red-max) < MagickEpsilon)
865 h=fmod((green-blue)/c+6.0,6.0);
867 if (fabs(green-max) < MagickEpsilon)
868 h=((blue-red)/c)+2.0;
870 if (fabs(blue-max) < MagickEpsilon)
871 h=((red-green)/c)+4.0;
873 *chroma=QuantumScale*c;
874 *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
905MagickPrivate
void ConvertRGBToHCLp(
const double red,
const double green,
906 const double blue,
double *hue,
double *chroma,
double *luma)
916 assert(hue != (
double *) NULL);
917 assert(chroma != (
double *) NULL);
918 assert(luma != (
double *) NULL);
919 max=MagickMax(red,MagickMax(green,blue));
920 c=max-MagickMin(red,MagickMin(green,blue));
922 if (fabs(c) < MagickEpsilon)
925 if (fabs(red-max) < MagickEpsilon)
926 h=fmod((green-blue)/c+6.0,6.0);
928 if (fabs(green-max) < MagickEpsilon)
929 h=((blue-red)/c)+2.0;
931 if (fabs(blue-max) < MagickEpsilon)
932 h=((red-green)/c)+4.0;
934 *chroma=QuantumScale*c;
935 *luma=QuantumScale*(0.298839*red+0.586811*green+0.114350*blue);
966MagickPrivate
void ConvertRGBToHSB(
const double red,
const double green,
967 const double blue,
double *hue,
double *saturation,
double *brightness)
977 assert(hue != (
double *) NULL);
978 assert(saturation != (
double *) NULL);
979 assert(brightness != (
double *) NULL);
983 min=red < green ? red : green;
986 max=red > green ? red : green;
989 if (fabs(max) < MagickEpsilon)
992 *saturation=delta/max;
993 *brightness=QuantumScale*max;
994 if (fabs(delta) < MagickEpsilon)
996 if (fabs(red-max) < MagickEpsilon)
997 *hue=(green-blue)/delta;
999 if (fabs(green-max) < MagickEpsilon)
1000 *hue=2.0+(blue-red)/delta;
1002 *hue=4.0+(red-green)/delta;
1036MagickPrivate
void ConvertRGBToHSI(
const double red,
const double green,
1037 const double blue,
double *hue,
double *saturation,
double *intensity)
1046 assert(hue != (
double *) NULL);
1047 assert(saturation != (
double *) NULL);
1048 assert(intensity != (
double *) NULL);
1049 *intensity=(QuantumScale*red+QuantumScale*green+QuantumScale*blue)/3.0;
1050 if (*intensity <= 0.0)
1056 *saturation=1.0-MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1057 QuantumScale*blue))/(*intensity);
1058 alpha=0.5*(2.0*QuantumScale*red-QuantumScale*green-QuantumScale*blue);
1059 beta=0.8660254037844385*(QuantumScale*green-QuantumScale*blue);
1060 *hue=atan2(beta,alpha)*(180.0/MagickPI)/360.0;
1093MagickExport
void ConvertRGBToHSL(
const double red,
const double green,
1094 const double blue,
double *hue,
double *saturation,
double *lightness)
1104 assert(hue != (
double *) NULL);
1105 assert(saturation != (
double *) NULL);
1106 assert(lightness != (
double *) NULL);
1107 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1108 QuantumScale*blue));
1109 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1110 QuantumScale*blue));
1112 *lightness=(max+min)/2.0;
1119 if (fabs(max-QuantumScale*red) < MagickEpsilon)
1121 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1122 if ((QuantumScale*green) < (QuantumScale*blue))
1126 if (fabs(max-QuantumScale*green) < MagickEpsilon)
1127 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1129 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1131 if (*lightness <= 0.5)
1132 *saturation=c*PerceptibleReciprocal(2.0*(*lightness));
1134 *saturation=c*PerceptibleReciprocal(2.0-2.0*(*lightness));
1165MagickPrivate
void ConvertRGBToHSV(
const double red,
const double green,
1166 const double blue,
double *hue,
double *saturation,
double *value)
1176 assert(hue != (
double *) NULL);
1177 assert(saturation != (
double *) NULL);
1178 assert(value != (
double *) NULL);
1179 max=MagickMax(QuantumScale*red,MagickMax(QuantumScale*green,
1180 QuantumScale*blue));
1181 min=MagickMin(QuantumScale*red,MagickMin(QuantumScale*green,
1182 QuantumScale*blue));
1191 if (fabs(max-QuantumScale*red) < MagickEpsilon)
1193 *hue=(QuantumScale*green-QuantumScale*blue)/c;
1194 if ((QuantumScale*green) < (QuantumScale*blue))
1198 if (fabs(max-QuantumScale*green) < MagickEpsilon)
1199 *hue=2.0+(QuantumScale*blue-QuantumScale*red)/c;
1201 *hue=4.0+(QuantumScale*red-QuantumScale*green)/c;
1203 *saturation=c*PerceptibleReciprocal(max);
1234MagickPrivate
void ConvertRGBToHWB(
const double red,
const double green,
1235 const double blue,
double *hue,
double *whiteness,
double *blackness)
1246 assert(hue != (
double *) NULL);
1247 assert(whiteness != (
double *) NULL);
1248 assert(blackness != (
double *) NULL);
1249 w=MagickMin(red,MagickMin(green,blue));
1250 v=MagickMax(red,MagickMax(green,blue));
1251 *blackness=1.0-QuantumScale*v;
1252 *whiteness=QuantumScale*w;
1253 if (fabs(v-w) < MagickEpsilon)
1258 f=(fabs(red-w) < MagickEpsilon) ? green-blue :
1259 ((fabs(green-w) < MagickEpsilon) ? blue-red : red-green);
1260 p=(fabs(red-w) < MagickEpsilon) ? 3.0 :
1261 ((fabs(green-w) < MagickEpsilon) ? 5.0 : 1.0);
1262 *hue=(p-f/(v-1.0*w))/6.0;
1292MagickPrivate
void ConvertRGBToLab(
const double red,
const double green,
1293 const double blue,
const IlluminantType illuminant,
double *L,
double *a,
1301 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1302 ConvertXYZToLab(X,Y,Z,illuminant,L,a,b);
1334static inline void ConvertXYZToLCHab(
const double X,
const double Y,
1335 const double Z,
const IlluminantType illuminant,
double *luma,
double *chroma,
1342 ConvertXYZToLab(X,Y,Z,illuminant,luma,&a,&b);
1343 *chroma=hypot(a-0.5,b-0.5)/1.0+0.5;
1344 *hue=180.0*atan2(b-0.5,a-0.5)/MagickPI/360.0;
1349MagickPrivate
void ConvertRGBToLCHab(
const double red,
const double green,
1350 const double blue,
const IlluminantType illuminant,
double *luma,
double *chroma,
1361 assert(luma != (
double *) NULL);
1362 assert(chroma != (
double *) NULL);
1363 assert(hue != (
double *) NULL);
1364 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1365 ConvertXYZToLCHab(X,Y,Z,illuminant,luma,chroma,hue);
1397static inline void ConvertXYZToLCHuv(
const double X,
const double Y,
1398 const double Z,
const IlluminantType illuminant,
double *luma,
double *chroma,
1405 ConvertXYZToLuv(X,Y,Z,illuminant,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;
1412MagickPrivate
void ConvertRGBToLCHuv(
const double red,
const double green,
1413 const double blue,
const IlluminantType illuminant,
double *luma,
double *chroma,
1424 assert(luma != (
double *) NULL);
1425 assert(chroma != (
double *) NULL);
1426 assert(hue != (
double *) NULL);
1427 ConvertRGBToXYZ(red,green,blue,&X,&Y,&Z);
1428 ConvertXYZToLCHuv(X,Y,Z,illuminant,luma,chroma,hue);
1458MagickExport
double ExpandAffine(
const AffineMatrix *affine)
1461 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
1493MagickPrivate
double GenerateDifferentialNoise(
RandomInfo *random_info,
1494 const Quantum pixel,
const NoiseType noise_type,
const double attenuate)
1496#define SigmaUniform (attenuate*0.015625)
1497#define SigmaGaussian (attenuate*0.015625)
1498#define SigmaImpulse (attenuate*0.1)
1499#define SigmaLaplacian (attenuate*0.0390625)
1500#define SigmaMultiplicativeGaussian (attenuate*0.5)
1501#define SigmaPoisson (attenuate*12.5)
1502#define SigmaRandom (attenuate)
1503#define TauGaussian (attenuate*0.078125)
1511 alpha=GetPseudoRandomValue(random_info);
1517 noise=(double) pixel+(
double) QuantumRange*SigmaUniform*(alpha-0.5);
1526 if (fabs(alpha) < MagickEpsilon)
1528 beta=GetPseudoRandomValue(random_info);
1529 gamma=sqrt(-2.0*log(alpha));
1530 sigma=gamma*cos((
double) (2.0*MagickPI*beta));
1531 tau=gamma*sin((
double) (2.0*MagickPI*beta));
1532 noise=(double) pixel+sqrt((
double) pixel)*SigmaGaussian*sigma+
1533 (
double) QuantumRange*TauGaussian*tau;
1538 if (alpha < (SigmaImpulse/2.0))
1541 if (alpha >= (1.0-(SigmaImpulse/2.0)))
1542 noise=(
double) QuantumRange;
1544 noise=(double) pixel;
1547 case LaplacianNoise:
1551 if (alpha <= MagickEpsilon)
1552 noise=(double) (pixel-QuantumRange);
1554 noise=(double) pixel+(
double) QuantumRange*SigmaLaplacian*
1559 if (beta <= (0.5*MagickEpsilon))
1560 noise=(double) (pixel+QuantumRange);
1562 noise=(double) pixel-(
double) QuantumRange*SigmaLaplacian*
1566 case MultiplicativeGaussianNoise:
1569 if (alpha > MagickEpsilon)
1570 sigma=sqrt(-2.0*log(alpha));
1571 beta=GetPseudoRandomValue(random_info);
1572 noise=(double) pixel+(
double) pixel*SigmaMultiplicativeGaussian*sigma*
1573 cos((
double) (2.0*MagickPI*beta))/2.0;
1584 poisson=exp(-SigmaPoisson*QuantumScale*(
double) pixel);
1585 for (i=0; alpha > poisson; i++)
1587 beta=GetPseudoRandomValue(random_info);
1590 noise=(double) QuantumRange*i*PerceptibleReciprocal(SigmaPoisson);
1595 noise=(double) QuantumRange*SigmaRandom*alpha;
1633MagickPrivate
size_t GetOptimalKernelWidth1D(
const double radius,
1650 if (IsEventLogging() != MagickFalse)
1651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1652 if (radius > MagickEpsilon)
1653 return((
size_t) (2.0*ceil(radius)+1.0));
1655 if (gamma <= MagickEpsilon)
1657 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1658 beta=(double) PerceptibleReciprocal((
double) MagickSQ2PI*gamma);
1662 j=(ssize_t) (width-1)/2;
1663 for (i=(-j); i <= j; i++)
1664 normalize+=exp(-((
double) (i*i))*alpha)*beta;
1665 value=exp(-((
double) (j*j))*alpha)*beta/normalize;
1666 if ((value < QuantumScale) || (value < MagickEpsilon))
1670 return((
size_t) (width-2));
1673MagickPrivate
size_t GetOptimalKernelWidth2D(
const double radius,
1691 if (IsEventLogging() != MagickFalse)
1692 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1693 if (radius > MagickEpsilon)
1694 return((
size_t) (2.0*ceil(radius)+1.0));
1696 if (gamma <= MagickEpsilon)
1698 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
1699 beta=(double) PerceptibleReciprocal((
double) Magick2PI*gamma*gamma);
1703 j=(ssize_t) (width-1)/2;
1704 for (v=(-j); v <= j; v++)
1705 for (u=(-j); u <= j; u++)
1706 normalize+=exp(-((
double) (u*u+v*v))*alpha)*beta;
1707 value=exp(-((
double) (j*j))*alpha)*beta/normalize;
1708 if ((value < QuantumScale) || (value < MagickEpsilon))
1712 return((
size_t) (width-2));
1715MagickPrivate
size_t GetOptimalKernelWidth(
const double radius,
1718 return(GetOptimalKernelWidth1D(radius,sigma));