import java.lang.Math.*; /** * TwoDArray is a data structure to represent a two-dimensional array * of complex numbers. ie The result of applying the 2D FFT to an image. * * @author Simon Horne. */ public class TwoDArray { /** * The actual width of the image represented by the TwoDArray. */ static public int width; /** * The actual height of the image represented by the TwoDArray. */ static public int height; /** * Smallest value of 2^n such that the 2^n > width and 2^n > height. * The dimensions of the square 2D array storing the image. */ public int size; /** * The 2D array of complex numbers padded out with (0,0) * to 2^n width and height. */ public ComplexNumber[][] values; /** * Default no-arg constructor. */ public TwoDArray() { } /** * Constructor that takes a TwoDArray and duplicates it exactly. * * @param a TwoDArray to be duplicated. */ public TwoDArray(TwoDArray a) { width = a.width; height = a.height; //System.out.println("NEW 2D 1 w: "+width+" height: "+height); size = a.size; values = new ComplexNumber[size][size]; for (int j = 0; j < size; ++j) { for (int i = 0; i < size; ++i) { ComplexNumber c = new ComplexNumber(a.values[i][j]); values[i][j] = c; } } } /** * Constructor that takes a width and a height, generates the appropriate * size values and then sets up an array of (0,0) complex numbers. * * @param w Width of the new TwoDArray. * @param h Height of the new TwoDArray. */ public TwoDArray(int w, int h) { width = w; height = h; //System.out.println("NEW 2D 2 w: "+width+" height: "+height); int n = 0; while (Math.pow(2, n) < Math.max(w, h)) { ++n; } size = (int) Math.pow(2, n); values = new ComplexNumber[size][size]; for (int j = 0; j < size; ++j) { for (int i = 0; i < size; ++i) { values[i][j] = new ComplexNumber(0, 0); } } } /** * Constructor that takes a single dimension, generates an appropriate * size and sets up a size x size array of (0,0) complex numbers. * * @param s Width or height of new TwoDArray. */ public TwoDArray(int s) { width = s; height = s; //System.out.println("NEW 2D 3 w: "+width+" height: "+height); int n = 0; while (Math.pow(2, n) < s) { ++n; } size = (int) Math.pow(2, n); values = new ComplexNumber[size][size]; for (int j = 0; j < size; ++j) { for (int i = 0; i < size; ++i) { values[i][j] = new ComplexNumber(0, 0); } } } /** * Constructor taking int array of pixel values and width and height * of the image represented by the array of pixels, sets values to * (x,0) for each pixel x. * * @param p int array of pixel values. * @param w Width of image. * @param h Height of image. */ public TwoDArray(double[] p, int w, int h) { width = w; height = h; //System.out.println("NEW 2D 4 w: "+width+" height: "+height); int n = 0; while (Math.pow(2, n) < Math.max(w, h)) { ++n; } //System.out.println("n is "+n+" w is "+w+" h is "+h); size = (int) Math.pow(2, n); values = new ComplexNumber[size][size]; /* for (int j = h; j < size; ++j) { for (int i = 0; i < size; ++i) { values[i][j] = new ComplexNumber(0, 0); } } for (int j = 0; j < size-h; ++j) { for (int i = w; i < size; ++i) { values[i][j] = new ComplexNumber(0, 0); } } */ /*System.err.println("Just about to add image to array");*/ /* DONALD NAIRN 2003 */ for (int j = 0; j < size; ++j) { for (int i = 0; i < size; ++i) { double real = 0; if (i < w && j < h) { real = p[i + (j * w)]; } values[i][j] = new ComplexNumber(real, 0.0); } } } /** * Constructor taking 2D int array of pixels values, width and height, * sets values to (x,0) for each pixel x. * * @param v 2D array of pixel values. * @param w Width of image. * @param h Height of image. */ public TwoDArray(int[][] v, int w, int h) { width = w; height = h; //System.out.println("NEW 2D 5 w: "+width+" height: "+height); int n = 0; while (Math.pow(2, n) < Math.max(w, h)) { ++n; } size = (int) Math.pow(2, n); values = new ComplexNumber[size][size]; for (int j = 0; j < size; ++j) { for (int i = 0; i < size; ++i) { values[i][j] = new ComplexNumber(0, 0); } } for (int j = 0; j < h; ++j) { for (int i = 0; i < w; ++i) { values[i][j] = new ComplexNumber(v[i][j], 0.0); } } } /** * Constructor taking 2D array of complex numbers, width and height. * * @param v 2D array of complex numbers. * @param w Width of image. * @param h Height of image. */ public TwoDArray(ComplexNumber[][] v, int w, int h) { width = w; height = h; //System.out.println("NEW 2D 6 w: "+width+" height: "+height); int n = 0; while (Math.pow(2, n) < Math.max(w, h)) { ++n; } size = (int) Math.pow(2, n); values = new ComplexNumber[size][size]; for (int j = 0; j < size; ++j) { for (int i = 0; i < size; ++i) { values[i][j] = new ComplexNumber(0, 0); } } for (int j = 0; j < h; ++j) { for (int i = 0; i < w; ++i) { values[i][j] = new ComplexNumber(v[i][j]); } } } /** * Takes a column number and returns an array containing the * complex numbers in that column. * * @param n int column number (0 is first column). * @return ComplexNumber array containing column. */ public ComplexNumber[] getColumn(int n) { ComplexNumber[] c = new ComplexNumber[size]; for (int i = 0; i < size; ++i) { c[i] = new ComplexNumber(values[n][i]); } return c; } /** * Takes a column number and an array of complex numbers and replaces * that column with the new data. * * @param n int column number (0 is first column). * @param Array of complex numbers representing the new data. */ public void putColumn(int n, ComplexNumber[] c) { for (int i = 0; i < size; ++i) { values[n][i] = new ComplexNumber(c[i]); } } /** * Takes a row number and an array of complex numbers and replaces * that row with the new data. * * @param n int row number (0 is first row). * @param c Array of complex numbers representing the new data. */ public void putRow(int n, ComplexNumber[] c) { for (int i = 0; i < size; ++i) { values[i][n] = new ComplexNumber(c[i]); } } /** * Takes a row number and returns an array containing the * complex numbers in that row. * * @param n int row number (0 is first row). * @return ComplexNumber array containing row. */ public ComplexNumber[] getRow(int n) { ComplexNumber[] r = new ComplexNumber[size]; for (int i = 0; i < size; ++i) { r[i] = new ComplexNumber(values[i][n]); } return r; } /** * Takes a 2D array of doubles representing an image and translates * and wraps the image to put (0,0) the DC value in the centre of the image. * at (width/2,height/2) [because image runs -128..+127] * * @param input 2D array of doubles. * @return 2D array of doubles representing the new image. */ public double[][] DCToCentre(double[][] input) { double[][] output = new double[width][height]; int x = width / 2; int y = height / 2; int i2, j2; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { i2 = i + x; j2 = j + y; if (i2 >= width) { i2 = i2 % width; } if (j2 >= height) { j2 = j2 % height; } output[i][j] = input[i2][j2]; } } return output; } /** * Takes a 2D array of doubles representing an image and translates * and wraps the image to put the centre pixel at (0,0). * * @param input 2D array of doubles. * @return 2D array of doubles representing the new image. */ public double[][] DCToTopLeft(double[][] input) { double[][] output = new double[width][height]; int i2, j2; int x = width / 2; int y = height / 2; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { i2 = i + x; j2 = j + x; if (i2 >= width) { i2 = i2 % width; } if (j2 >= height) { j2 = j2 % height; } output[i][j] = input[i2][j2]; } } return output; } static public ComplexNumber[][] DCToTopLeft(ComplexNumber[][] input) { ComplexNumber[][] output = new ComplexNumber[width][height]; int i2, j2; int x = width / 2; int y = height / 2; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { i2 = i + x; j2 = j + x; if (i2 >= width) { i2 = i2 % width; } if (j2 >= height) { j2 = j2 % height; } output[i][j] = input[i2][j2]; } } return output; } /** * Takes an array of doubles representing an image and translates * and wraps the image to put (0,0) the DC value in the centre of the image. * at (width/2,height/2) [because image runs -128..+127] * * @param input array of doubles. * @return array of doubles representing the new image. */ static public double[] DCToCentre(double[] input) { double[][] input2 = new double[width][height]; double[][] output2 = new double[width][height]; double[] output = new double[width * height]; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { input2[i][j] = input[j * width + i]; } } int x = width / 2; int y = height / 2; int i2, j2; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { i2 = i + x; j2 = j + y; //if (input2[i][j] == 0){System.out.println("ZEROa at ("+i+","+j+") moved to ("+i2+","+j2+")");} if (i2 >= width) { i2 = i2 % width; } if (j2 >= height) { j2 = j2 % height; } output2[i][j] = input2[i2][j2]; } } for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { output[j * width + i] = output2[i][j]; } } return output; } /** * Method to extract the real parts from a TwoDArray. * * @return An array of doubles representing the real parts of * each element of the TwoDArray. */ public double[] getReal() { double[] output = new double[width * height]; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { output[(j * width) + i] = values[i][j].real; //if (values[i][j].real == 0){System.out.println("found ZERO at ("+i+","+j+")");} } } return output; } /** * Method to extract the imaginary parts from a TwoDArray. * * @return An array of doubles representing the imaginary parts of * each element of the TwoDArray. */ public double[] getImaginary() { double[] output = new double[width * height]; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { output[(j * width) + i] = values[i][j].imaginary; } } return output; } /** * Method to extract the magnitude of each element from a TwoDArray. * * @return An array of doubles representing the magnitude of * each element of the TwoDArray. */ public double[] getMagnitude() { double[] output = new double[width * height]; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { output[(j * width) + i] = values[i][j].magnitude(); } } return output; } /** * Method to extract the phase angle of each element from a TwoDArray. * * @return An array of doubles representing the phase angle of * each element of the TwoDArray. */ public double[] getPhase() { double[] output = new double[width * height]; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { output[(j * width) + i] = values[i][j].phaseAngle(); } } return output; } }