23 #define M_SQRT1_2 0.70710678118654752440084436210484904
28 #define M_PI 3.14159265358979323846264338327950288
32 static int KernelRescale(
image *Kernel)
35 num *Data = Kernel->
Data;
39 for(n = 0; n < NumEl; n++)
44 fprintf(stderr,
"Kernel must have nonzero sum.\n");
48 for(n = 0; n < NumEl; n++)
55 static int GaussianKernel(
image *Kernel, num Sigma)
57 const int R = (int)ceil(4*Sigma);
58 const int W = 2*R + 1;
59 const double ExpDenom = 2.0*(double)Sigma*(
double)Sigma;
65 if(!Kernel || Sigma < 0.0 || !(AllocImageObj(Kernel, W, W, 1)))
74 for(y = -R, Sum = 0; y <= R; y++)
75 for(x = -R; x <= R; x++)
77 Data[(R + x) + W*(R + y)] = (num)exp(-(x*x + y*y)/ExpDenom);
78 Sum += Data[(R + x) + W*(R + y)];
81 for(y = -R; y <= R; y++)
82 for(x = -R; x <= R; x++)
83 Data[(R + x) + W*(R + y)] =
84 (num)(Data[(R + x) + W*(R + y)]/Sum);
91 static int DiskKernel(
image *Kernel, num Radius)
93 const int R = (int)ceil(Radius - 0.5);
94 const int W = 2*R + 1;
96 const double RadiusSqr = (double)Radius*(
double)Radius;
97 const double RadiusInnerSqr =
99 const double RadiusOuterSqr =
102 double Sum, xl, yl, Start = -0.5 + 0.5/Res, Step = 1.0/Res;
106 if(!Kernel || Radius < 0.0 || !(AllocImageObj(Kernel, W, W, 1)))
115 for(y = -R, Sum = 0; y <= R; y++)
116 for(x = -R; x <= R; x++)
118 if(x*x + y*y <= RadiusInnerSqr)
120 else if(x*x + y*y > RadiusOuterSqr)
123 for(n = 0, yl = y + Start, c = 0; n < Res; n++, yl += Step)
124 for(m = 0, xl = x + Start; m < Res; m++, xl += Step)
125 if(xl*xl + yl*yl <= RadiusSqr)
128 Data[(R + x) + W*(R + y)] = (num)c;
132 for(y = -R; y <= R; y++)
133 for(x = -R; x <= R; x++)
134 Data[(R + x) + W*(R + y)] =
135 (num)(Data[(R + x) + W*(R + y)]/Sum);
142 static int MakeNamedKernel(
image *Kernel,
const char *String)
144 const char *ColonPtr;
149 if(!Kernel || !(ColonPtr = strchr(String,
':'))
150 || (Length = (
int)(ColonPtr - String)) > 9)
153 strncpy(KernelName, String, Length);
154 KernelName[Length] =
'\0';
155 KernelParam = (num)atof(ColonPtr + 1);
157 if(!strcmp(KernelName,
"Gaussian") || !strcmp(KernelName,
"gaussian"))
158 return GaussianKernel(Kernel, KernelParam);
159 else if(!strcmp(KernelName,
"Disk") || !strcmp(KernelName,
"disk"))
160 return DiskKernel(Kernel, KernelParam);
179 FreeImageObj(*Kernel);
183 if(MakeNamedKernel(Kernel, String)