Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

233 lines
6.5 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkImageFourierFilter.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkImageFourierFilter.h"
#include <math.h>
vtkCxxRevisionMacro(vtkImageFourierFilter, "$Revision: 1.18 $");
/*=========================================================================
Vectors of complex numbers.
=========================================================================*/
//----------------------------------------------------------------------------
// This function calculates one step of a FFT.
// It is specialized for a factor of 2.
// It is engineered for no decimation.
// (forward: fb = 1, backward: fb = -1)
void vtkImageFourierFilter::ExecuteFftStep2(vtkImageComplex *p_in,
vtkImageComplex *p_out,
int N, int bsize, int fb)
{
int i1, i2;
vtkImageComplex *p1, *p2, *p3;
vtkImageComplex q, fact1, fact, temp;
/* Copy the links with no factors. */
p1 = p_in;
p3 = p_out;
for(i1 = 0; i1 < N / (bsize * 2); ++i1) // loop 0->1
{
p2 = p1;
for(i2 = 0; i2 < bsize; ++i2) // loop 0->2
{
*p3 = *p2; // out[0] = in[0]; out[1] = in[1];
++p2;
++p3;
}
p2 = p1;
for(i2 = 0; i2 < bsize; ++i2)
{
*p3 = *p2; // out[2] = in[0]; out[3] = in[1];
++p2;
++p3;
}
p1 = p1 + bsize;
}
/* Add the links with factors. */
fact1.Real = 1.0;
fact1.Imag = 0.0;
q.Real = 0.0;
q.Imag = -2.0 * 3.141592654 * (float)(fb) / (float)(bsize * 2);
vtkImageComplexExponential(q, q);
p3 = p_out;
for(i1 = 0; i1 < N / (bsize * 2); ++i1)
{
fact = fact1;
p2 = p1;
for(i2 = 0; i2 < bsize; ++i2)
{
vtkImageComplexMultiply(fact, *p2, temp);
vtkImageComplexAdd(temp, *p3, *p3);
vtkImageComplexMultiply(q, fact, fact);
++p2; // out[0] += in[2]; out[1] += -i*in[3];
++p3;
}
p2 = p1;
for(i2 = 0; i2 < bsize; ++i2)
{
vtkImageComplexMultiply(fact, *p2, temp);
vtkImageComplexAdd(temp, *p3, *p3);
vtkImageComplexMultiply(q, fact, fact);
++p2;
++p3;
}
p1 = p1 + bsize;
}
}
//----------------------------------------------------------------------------
// This function calculates one step of a FFT (using any factor).
// It is engineered for no decimation.
// N: length of arrays
// bsize: Size of FFT so far (should be scaled by n after this step)
// n: size of this steps butterfly.
// fb: forward: fb = 1, backward: fb = -1
void vtkImageFourierFilter::ExecuteFftStepN(vtkImageComplex *p_in,
vtkImageComplex *p_out,
int N, int bsize, int n, int fb)
{
int i0, i1, i2, i3;
vtkImageComplex *p1, *p2, *p3;
vtkImageComplex q, fact, temp;
p3 = p_out;
for(i0 = 0; i0 < N; ++i0)
{
p3->Real = 0.0;
p3->Imag = 0.0;
++p3;
}
p1 = p_in;
for(i0 = 0; i0 < n; ++i0)
{
q.Real = 0.0;
q.Imag = -2.0 * 3.141592654 * (float)(i0) * (float)(fb) / (float)(bsize*n);
vtkImageComplexExponential(q, q);
p3 = p_out;
for(i1 = 0; i1 < N / (bsize * n); ++i1)
{
fact.Real = 1.0;
fact.Imag = 0.0;
for(i3 = 0; i3 < n; ++i3)
{
p2 = p1;
for(i2 = 0; i2 < bsize; ++i2)
{
vtkImageComplexMultiply(fact, *p2, temp);
vtkImageComplexAdd(temp, *p3, *p3);
vtkImageComplexMultiply(q, fact, fact);
++p2;
++p3;
}
}
p1 = p1 + bsize;
}
}
}
//----------------------------------------------------------------------------
// This function calculates the whole fft (or rfft) of an array.
// The contents of the input array are changed.
// It is engineered for no decimation so input and output cannot be equal.
// (fb = 1) => fft, (fb = -1) => rfft;
void vtkImageFourierFilter::ExecuteFftForwardBackward(vtkImageComplex *in,
vtkImageComplex *out,
int N, int fb)
{
vtkImageComplex *p1, *p2, *p3;
int block_size = 1;
int rest_size = N;
int n = 2;
int idx;
// If this is a reverse transform (scale accordingly).
if(fb == -1)
{
p1 = in;
for(idx = 0; idx < N; ++idx)
{
p1->Real = p1->Real / (float)(N);
p1->Imag = p1->Imag / (float)(N);
++p1;
}
}
p1 = in;
p2 = out;
while(block_size < N && n <= N)
{
if((rest_size % n) == 0)
{
// n is a prime factor, perform one "butterfly" stage of the fft.
if(n == 2)
{
this->ExecuteFftStep2(p1, p2, N, block_size, fb);
}
else
{
this->ExecuteFftStepN(p1, p2, N, block_size, n, fb);
}
block_size = block_size * n;
rest_size = rest_size / n;
// switch input and output.
p3 = p1;
p1 = p2;
p2 = p3;
}
else
{
// n is not a prime factor. increment n to see if n+1 is.
++n;
}
}
// If the results ended up in the input, copy to output.
if(p1 != out)
{
for(n = 0; n < N; ++n)
{
*out++ = *p1++;
}
}
}
//----------------------------------------------------------------------------
// This function calculates the whole fft of an array.
// The contents of the input array are changed.
// (It is engineered for no decimation)
void vtkImageFourierFilter::ExecuteFft(vtkImageComplex *in,
vtkImageComplex *out, int N)
{
this->ExecuteFftForwardBackward(in, out, N, 1);
}
//----------------------------------------------------------------------------
// This function calculates the whole fft of an array.
// The contents of the input array are changed.
// (It is engineered for no decimation)
void vtkImageFourierFilter::ExecuteRfft(vtkImageComplex *in,
vtkImageComplex *out, int N)
{
this->ExecuteFftForwardBackward(in, out, N, -1);
}