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"
87MagickExport
double ExpandAffine(
const AffineMatrix *affine)
90 return(sqrt(fabs(affine->sx*affine->sy-affine->rx*affine->ry)));
122MagickPrivate
double GenerateDifferentialNoise(
RandomInfo *random_info,
123 const Quantum pixel,
const NoiseType noise_type,
const double attenuate)
125#define SigmaUniform (attenuate*0.015625)
126#define SigmaGaussian (attenuate*0.015625)
127#define SigmaImpulse (attenuate*0.1)
128#define SigmaLaplacian (attenuate*0.0390625)
129#define SigmaMultiplicativeGaussian (attenuate*0.5)
130#define SigmaPoisson (attenuate*12.5)
131#define SigmaRandom (attenuate)
132#define TauGaussian (attenuate*0.078125)
140 alpha=GetPseudoRandomValue(random_info);
146 noise=(double) pixel+(
double) QuantumRange*SigmaUniform*(alpha-0.5);
155 if (fabs(alpha) < MagickEpsilon)
157 beta=GetPseudoRandomValue(random_info);
158 gamma=sqrt(-2.0*log(alpha));
159 sigma=gamma*cos((
double) (2.0*MagickPI*beta));
160 tau=gamma*sin((
double) (2.0*MagickPI*beta));
161 noise=(double) pixel+sqrt((
double) pixel)*SigmaGaussian*sigma+
162 (double) QuantumRange*TauGaussian*tau;
167 if (alpha < (SigmaImpulse/2.0))
170 if (alpha >= (1.0-(SigmaImpulse/2.0)))
171 noise=(double) QuantumRange;
173 noise=(double) pixel;
180 if (alpha <= MagickEpsilon)
181 noise=(double) (pixel-QuantumRange);
183 noise=(double) pixel+(
double) QuantumRange*SigmaLaplacian*
188 if (beta <= (0.5*MagickEpsilon))
189 noise=(double) (pixel+QuantumRange);
191 noise=(double) pixel-(
double) QuantumRange*SigmaLaplacian*
195 case MultiplicativeGaussianNoise:
198 if (alpha > MagickEpsilon)
199 sigma=sqrt(-2.0*log(alpha));
200 beta=GetPseudoRandomValue(random_info);
201 noise=(double) pixel+(
double) pixel*SigmaMultiplicativeGaussian*sigma*
202 cos((
double) (2.0*MagickPI*beta))/2.0;
213 poisson=exp(-SigmaPoisson*QuantumScale*(
double) pixel);
214 for (i=0; alpha > poisson; i++)
216 beta=GetPseudoRandomValue(random_info);
219 noise=(double) QuantumRange*i*PerceptibleReciprocal(SigmaPoisson);
224 noise=(double) QuantumRange*SigmaRandom*alpha;
262MagickPrivate
size_t GetOptimalKernelWidth1D(
const double radius,
279 if (IsEventLogging() != MagickFalse)
280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
281 if (radius > MagickEpsilon)
282 return((
size_t) (2.0*ceil(radius)+1.0));
284 if (gamma <= MagickEpsilon)
286 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
287 beta=(double) PerceptibleReciprocal((
double) MagickSQ2PI*gamma);
291 j=(ssize_t) (width-1)/2;
292 for (i=(-j); i <= j; i++)
293 normalize+=exp(-((
double) (i*i))*alpha)*beta;
294 value=exp(-((
double) (j*j))*alpha)*beta/normalize;
295 if ((value < QuantumScale) || (value < MagickEpsilon))
299 return((
size_t) (width-2));
302MagickPrivate
size_t GetOptimalKernelWidth2D(
const double radius,
320 if (IsEventLogging() != MagickFalse)
321 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
322 if (radius > MagickEpsilon)
323 return((
size_t) (2.0*ceil(radius)+1.0));
325 if (gamma <= MagickEpsilon)
327 alpha=PerceptibleReciprocal(2.0*gamma*gamma);
328 beta=(double) PerceptibleReciprocal((
double) Magick2PI*gamma*gamma);
332 j=(ssize_t) (width-1)/2;
333 for (v=(-j); v <= j; v++)
334 for (u=(-j); u <= j; u++)
335 normalize+=exp(-((
double) (u*u+v*v))*alpha)*beta;
336 value=exp(-((
double) (j*j))*alpha)*beta/normalize;
337 if ((value < QuantumScale) || (value < MagickEpsilon))
341 return((
size_t) (width-2));
344MagickPrivate
size_t GetOptimalKernelWidth(
const double radius,
347 return(GetOptimalKernelWidth1D(radius,sigma));