using System.Drawing.Imaging;
using System.Windows.Forms;
namespace Fourier_Transform__Test
public static int Pow2(int power)
return ((power >= 0) && (power <= 30)) ? (1 << power) : 0;
public static int Log2(int x)
public static bool IsPowerOf2(int x)
return (x > 0) ? ((x & (x - 1)) == 0) : false;
public static class FourierTransform
private static void FastFourierTransform1d(Complex[] data, Direction direction)
for (int k = 1; k <= m; k++)
Complex[] rotation = FourierTransform.GetComplexRotation(k, direction);
for (int i = 0; i < tm; i++)
for (int even = i; even < n; even += tn)
double tr = co.Real * t.Real - co.Imaginary * t.Imaginary;
double ti = co.Real * t.Imaginary + co.Imaginary * t.Real;
data[even] += new Complex(tr, ti);
data[odd] = new Complex(ce.Real - tr, ce.Imaginary - ti);
if (direction == Direction.Forward)
for (int i = 0; i < data.Length; i++)
public static void FastFourierTransform2d(Complex[, ] data, Direction direction)
int k = data.GetLength(0);
int n = data.GetLength(1);
if (!Tools.IsPowerOf2(k) || !Tools.IsPowerOf2(n))
throw new ArgumentException("The matrix rows and columns must be a power of 2.");
if (k < minLength || k > maxLength || n < minLength || n > maxLength)
throw new ArgumentException("Incorrect cInputFft length.");
var row = new Complex[n];
for (int i = 0; i < k; i++)
for (int j = 0; j < row.Length; j++)
FourierTransform.FastFourierTransform1d(row, direction);
for (int j = 0; j < row.Length; j++)
var col = new Complex[k];
for (int j = 0; j < n; j++)
for (int i = 0; i < k; i++)
FourierTransform.FastFourierTransform1d(col, direction);
for (int i = 0; i < k; i++)
private const int minLength = 2;
private const int maxLength = 16384;
private const int minBits = 1;
private const int maxBits = 14;
private static int[][] reversedBits = new int[maxBits][];
private static Complex[, ][] complexRotation = new Complex[maxBits, 2][];
private static int[] GetReversedBits(int numberOfBits)
if ((numberOfBits < minBits) || (numberOfBits > maxBits))
throw new ArgumentOutOfRangeException();
if (reversedBits[numberOfBits - 1] == null)
int n = Tools.Pow2(numberOfBits);
int[] rBits = new int[n];
for (int i = 0; i < n; i++)
for (int j = 0; j < numberOfBits; j++)
newBits = (newBits << 1) | (oldBits & 1);
oldBits = (oldBits >> 1);
reversedBits[numberOfBits - 1] = rBits;
return reversedBits[numberOfBits - 1];
private static Complex[] GetComplexRotation(int numberOfBits, Direction direction)
int directionIndex = (direction == Direction.Forward) ? 0 : 1;
if (complexRotation[numberOfBits - 1, directionIndex] == null)
int n = 1 << (numberOfBits - 1);
double angle = System.Math.PI / n * (int)direction;
double wR = System.Math.Cos(angle);
double wI = System.Math.Sin(angle);
Complex[] rotation = new Complex[n];
for (int i = 0; i < n; i++)
rotation[i] = new Complex(uR, uI);
complexRotation[numberOfBits - 1, directionIndex] = rotation;
return complexRotation[numberOfBits - 1, directionIndex];
private static void ReorderData(Complex[] data)
if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len)))
throw new ArgumentException("Incorrect cInputFft length.");
int[] rBits = GetReversedBits(Tools.Log2(len));
for (int i = 0; i < len; i++)
public class FourierImageOperation
public static Complex[, ] FastFourierTransform2d(Complex[, ] image)
Complex[, ] comp = (Complex[, ])image.Clone();
int Width = comp.GetLength(0);
int Height = comp.GetLength(1);
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
if (((x + y) & 0x1) != 0)
FourierTransform.FastFourierTransform2d(comp, Direction.Forward);
public static Complex[, ] InverseFourierTransform2d(Complex[, ] image)
int Width = image.GetLength(0);
int Height = image.GetLength(1);
FourierTransform.FastFourierTransform2d(image, Direction.Backward);
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
if (((x + y) & 0x1) != 0)
public partial class MainForm : Form
string path = @"lena.png";
private void loadImageButton_Click(object sender, EventArgs e)
Bitmap bitmap = Bitmap.FromFile(path) as Bitmap;
originalImagePictureBox.Image = bitmap as Image;
private void grayscaleButton_Click(object sender, EventArgs e)
Bitmap originalImage = originalImagePictureBox.Image as Bitmap;
Bitmap grayscale = Grayscale.ToGrayscale(originalImage);
grayscaleImagePictureBox.Image = grayscale as Image;
private void fftButton_Click(object sender, EventArgs e)
Bitmap grayscale = grayscaleImagePictureBox.Image as Bitmap;
Complex[, ] cGrayscale = ImageDataConverter.ToComplex(grayscale);
Complex[, ] cFFt = FourierImageOperation.FastFourierTransform2d(cGrayscale);
fftPictureBox.Image = ImageDataConverter.ToBitmap(cFFt, true);
private void ifftButton_Click(object sender, EventArgs e)
Bitmap fftImage = fftPictureBox.Image as Bitmap;
Complex[, ] image = ImageDataConverter.ToComplex(fftImage);
Complex[, ] cGrayscale = FourierImageOperation.InverseFourierTransform2d(image);
ifftPictureBox.Image = ImageDataConverter.ToBitmap(image, false);