import java.lang.Math.*; import java.awt.*; /** * The InverseFFT class contains a method to apply the 2D inverse FFT to a * TwoDArray. * * @author Simon Horne */ public class InverseFFT { static public int progress; /** * Default no argument constructor. */ public InverseFFT() { } static ComplexNumber cTwo = new ComplexNumber(2, 0); /** * Recursively applies the 1D inverse FFT algorithm. * * @param x ComplexNumber array containing the input to the 1D inverse FFT. * @return ComplexNumber array containing the result of the 1D inverse FFT. */ static public ComplexNumber[] recursiveInverseFFT(ComplexNumber[] x) { ComplexNumber z1, z2, z3, z4, tmp; int n = x.length; int m = n / 2; ComplexNumber[] result = new ComplexNumber[n]; ComplexNumber[] even = new ComplexNumber[m]; ComplexNumber[] odd = new ComplexNumber[m]; ComplexNumber[] sum = new ComplexNumber[m]; ComplexNumber[] diff = new ComplexNumber[m]; if (n == 1) { result[0] = x[0]; } else { z1 = new ComplexNumber(0.0, 2 * (Math.PI) / n); tmp = ComplexNumber.cExp(z1); z1 = new ComplexNumber(1.0, 0.0); for (int i = 0; i < m; ++i) { z3 = ComplexNumber.cSum(x[i], x[i + m]); sum[i] = ComplexNumber.cDiv(z3, cTwo); z3 = ComplexNumber.cDif(x[i], x[i + m]); z4 = ComplexNumber.cMult(z3, z1); diff[i] = ComplexNumber.cDiv(z4, cTwo); z2 = ComplexNumber.cMult(z1, tmp); z1 = new ComplexNumber(z2); } even = recursiveInverseFFT(sum); odd = recursiveInverseFFT(diff); for (int i = 0; i < m; ++i) { result[i * 2] = new ComplexNumber(even[i]); result[i * 2 + 1] = new ComplexNumber(odd[i]); } } return result; } /** * Takes a TwoDArray, applies the 2D inverse FFT to the input by applying * the 1D inverse FFT to each column and then each row in turn. * * @param input TwoDArray containing the input image data. * @return TwoDArray containing the new image data. */ static public TwoDArray transform(TwoDArray input) { progress = 0; TwoDArray intermediate = new TwoDArray(input.width, input.height); TwoDArray output = new TwoDArray(input.width, input.height); for (int i = 0; i < input.size; ++i) { progress++; intermediate.putColumn(i, recursiveInverseFFT(input.getColumn(i))); } for (int i = 0; i < intermediate.size; ++i) { progress++; output.putRow(i, recursiveInverseFFT(intermediate.getRow(i))); } return output; } static public int[] getPixels(TwoDArray output) { double[] outputArrayDoubles = new double[output.width * output.height]; outputArrayDoubles = output.getReal(); //outputArrayDoubles = fft.output.getMagnitude(); int[] outputArray; // = new int [outputArrayDoubles.length]; //outputArray = ImageMods.toPixels(outputArrayDoubles); outputArray = toPixels(allPositive(outputArrayDoubles)); return outputArray; } /** * Method to slide and scale an array of doubles so that the minimum * values is 0 (all positive). * * @param values An array of doubles. * @return An array of positive doubles. */ static private double[] allPositive(double[] values) { double[] output = new double[values.length]; double m = minValue(values); if (false) // m<0) { for (int i = 0; i < values.length; ++i) { output[i] = values[i] - m; } return output; } else { return values; } } static int[] toInts(double[] values) { int[] ints = new int[values.length]; double scale = 1; // 1024 * 16; // ??? for (int i = 0; i < values.length; ++i) { ints[i] = (int) (values[i]*scale); } return ints; } /** * A method to convert an array of grey values to an array of pixel values. * * @param values An array of grey values (all positive). * @return An array of pixel values. */ static int[] toPixels(double[] values) { int grey; // double [] greys = new double [values.length]; int[] pixels = new int[values.length]; // for(int i=0;i max) { max = values[i]; } } return max; } /** * Method to find the minimum value from an array of doubles. * * @param values an array of doubles. * @return The minimum value. */ static private double minValue(double[] values) { double min = values[0]; for (int i = 1; i < values.length; ++i) { if (values[i] < min) { min = values[i]; } } return min; } static public int getProgress() { return progress; } }