21 #define CLAMP(X,A,B) (((X) < (A)) ? (A) : (((X) > (B)) ? (B) : (X)))
42 int nStart,
int nStep,
int nEnd)
44 const int SrcStrideStep = SrcStride*nStep;
45 const int LeftmostTap = 1 - Filter.
Delay - Filter.
Length;
46 const int StartInterior =
CLAMP(-LeftmostTap, 0, N - 1);
47 const int EndInterior = (Filter.
Delay < 0) ?
48 (N + Filter.
Delay - 1) : (N - 1);
49 const float *SrcN, *SrcK;
54 if(nEnd < nStart || nStep <= 0 || N <= 0)
58 for(n = nStart; n < StartInterior; n += nStep, Dest += DestStride)
60 for(k = 0, Accum = 0; k < Filter.
Length; k++)
61 Accum += Filter.
Coeff[k]
62 * Boundary(Src, SrcStride, N, n - Filter.
Delay - k);
78 SrcN = (LeftmostTap <= 0) ? Src : (Src + SrcStride*LeftmostTap);
81 SrcN += SrcStride*(n - StartInterior);
83 for(; n <= EndInterior; n += nStep, SrcN += SrcStrideStep, Dest += DestStride)
91 Accum += Filter.
Coeff[--k] * (*SrcK);
99 for(; n <= nEnd; n += nStep, Dest += DestStride)
101 for(k = 0, Accum = 0; k < Filter.
Length; k++)
102 Accum += Filter.
Coeff[k]
103 * Boundary(Src, SrcStride, N, n - Filter.
Delay - k);
125 int Width,
int Height,
int NumChannels)
127 const int NumPixels = Width*Height;
130 for(Channel = 0; Channel < NumChannels; Channel++)
133 for(i = 0; i < Height; i++)
134 Conv1D(Buffer + Width*i, 1, Src + Width*i, 1,
135 FilterX, Boundary, Width);
138 for(i = 0; i < Width; i++)
139 Conv1D(Dest + i, Width, Buffer + i, Width, FilterY,
153 Filter.
Coeff = Coeff;
154 Filter.
Delay = Delay;
165 if(Length > 0 && (Coeff = (
float *)
Malloc(
sizeof(
float)*Length)))
175 return (Filter.
Coeff == NULL) ? 1:0;
207 for(r = -R, Sum = 0; r <= R; r++)
209 Filter.
Coeff[R + r] = (float)exp(-r*r/(2*Sigma*Sigma));
210 Sum += Filter.
Coeff[R + r];
213 for(r = -R; r <= R; r++)
214 Filter.
Coeff[R + r] /= Sum;
222 static float ZeroPaddedExtension(
const float *Src,
int Stride,
int N,
int n)
224 return (0 <= n && n < N) ? Src[Stride*n] : 0;
228 static float ConstantExtension(
const float *Src,
int Stride,
int N,
int n)
230 return Src[(n < 0) ? 0 : ((n >= N) ? Stride*(N - 1) : n)];
234 static float LinearExtension(
const float *Src,
int Stride,
int N,
int n)
239 return Src[Stride*n];
244 Src += Stride*(N - 1);
245 return Src[0] + (N - 1 - n)*(Src[-Stride] - Src[0]);
251 return Src[0] + n*(Src[Stride] - Src[0]);
255 static float PeriodicExtension(
const float *Src,
int Stride,
int N,
int n)
272 return Src[Stride*n];
276 static float SymhExtension(
const float *Src,
int Stride,
int N,
int n)
288 return Src[Stride*n];
292 static float SymwExtension(
const float *Src,
int Stride,
int N,
int n)
304 return Src[Stride*n];
308 static float AsymhExtension(
const float *Src,
int Stride,
int N,
int n)
317 return Src[Stride*n];
318 else if(n <= 2*N - 1)
319 return 3*Src[Stride*(N - 1)] - Src[Stride*(N - 2)]
320 - Src[Stride*(2*N - 1 - n)];
323 return 3*Src[0] - Src[Stride] - Src[Stride*(-1 - n)];
330 Jump = 3*(Src[Stride*(N - 1)] - Src[0])
331 - (Src[Stride*(N - 2)] - Src[Stride]);
352 return Src[Stride*n] + Offset;
354 return 3*Src[0] - Src[Stride] - Src[Stride*(-1 - n)] + Offset;
358 static float AsymwExtension(
const float *Src,
int Stride,
int N,
int n)
367 return Src[Stride*n];
369 return 2*Src[Stride*(N - 1)] - Src[Stride*(2*(N - 1) - n)];
372 return 2*Src[0] - Src[Stride*(-n)];
379 Jump = 2*(Src[Stride*(N - 1)] - Src[0]);
400 return Src[Stride*n] + Offset;
402 return 2*Src[0] - Src[Stride*(-n)] + Offset;
423 if(!strcmp(Boundary,
"zpd") || !strcmp(Boundary,
"zero"))
424 return ZeroPaddedExtension;
425 else if(!strcmp(Boundary,
"sp0") || !strcmp(Boundary,
"const"))
426 return ConstantExtension;
427 else if(!strcmp(Boundary,
"sp1") || !strcmp(Boundary,
"linear"))
428 return LinearExtension;
429 else if(!strcmp(Boundary,
"per") || !strcmp(Boundary,
"periodic"))
430 return PeriodicExtension;
431 else if(!strcmp(Boundary,
"sym")
432 || !strcmp(Boundary,
"symh") || !strcmp(Boundary,
"hsym"))
433 return SymhExtension;
434 else if(!strcmp(Boundary,
"symw") || !strcmp(Boundary,
"wsym"))
435 return SymwExtension;
436 else if(!strcmp(Boundary,
"asym")
437 || !strcmp(Boundary,
"asymh") || !strcmp(Boundary,
"hasym"))
438 return AsymhExtension;
439 else if(!strcmp(Boundary,
"asymw") || !strcmp(Boundary,
"wasym"))
440 return AsymwExtension;
443 ErrorMessage(
"Unknown boundary extension \"%s\".\n", Boundary);