public void transform2D( float[] real, float[] imag, int cols, int rows, boolean forward ) {
        int log2cols = log2(cols);
        int log2rows = log2(rows);
        int n = Math.max(rows, cols);
        float[] rtemp = new float[n];
        float[] itemp = new float[n];

        // FFT the rows
        for ( int y = 0; y < rows; y++ ) {
            int offset = y*cols;
            System.arraycopy( real, offset, rtemp, 0, cols );
            System.arraycopy( imag, offset, itemp, 0, cols );
            transform1D(rtemp, itemp, log2cols, cols, forward);
            System.arraycopy( rtemp, 0, real, offset, cols );
            System.arraycopy( itemp, 0, imag, offset, cols );
        }

        // FFT the columns
        for ( int x = 0; x < cols; x++ ) {
            int index = x;
            for ( int y = 0; y < rows; y++ ) {
                rtemp[y] = real[index];
                itemp[y] = imag[index];
                index += cols;
            }
            transform1D(rtemp, itemp, log2rows, rows, forward);
            index = x;
            for ( int y = 0; y < rows; y++ ) {
                real[index] = rtemp[y];
                imag[index] = itemp[y];
                index += cols;
            }
        }
    }