|
@@ -18,29 +18,38 @@
|
|
|
#include <grass/gis.h>
|
|
|
#include <grass/glocale.h>
|
|
|
#include <grass/gmath.h>
|
|
|
-#include "globals.h"
|
|
|
-#include "local_proto.h"
|
|
|
|
|
|
-char Cellmap_real[GNAME_MAX], Cellmap_imag[GNAME_MAX];
|
|
|
+static void fft_colors(const char *name)
|
|
|
+{
|
|
|
+ struct Colors colors;
|
|
|
+ struct FPRange range;
|
|
|
+ DCELL min, max;
|
|
|
+
|
|
|
+ /* make a real component color table */
|
|
|
+ G_read_fp_range(name, G_mapset(), &range);
|
|
|
+ G_get_fp_range_min_max(&range, &min, &max);
|
|
|
+ G_make_grey_scale_fp_colors(&colors, min, max);
|
|
|
+ G_write_colors(name, G_mapset(), &colors);
|
|
|
+}
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
{
|
|
|
/* Global variable & function declarations */
|
|
|
- char Cellmap_orig[GNAME_MAX];
|
|
|
- FILE *realfp, *imagfp; /* the input and output file descriptors */
|
|
|
- int outputfd, maskfd; /* the input and output file descriptors */
|
|
|
- char *realmapset, *imagmapset; /* the input mapset names */
|
|
|
- struct Cell_head orig_wind, realhead;
|
|
|
- CELL *cell_row, *maskbuf = NULL;
|
|
|
+ struct GModule *module;
|
|
|
+ struct {
|
|
|
+ struct Option *orig, *real, *imag;
|
|
|
+ } opt;
|
|
|
+ const char *Cellmap_real, *Cellmap_imag;
|
|
|
+ const char *Cellmap_orig;
|
|
|
+ int realfd, imagfd, outputfd, maskfd; /* the input and output file descriptors */
|
|
|
+ struct Cell_head realhead, imaghead;
|
|
|
+ DCELL *cell_real, *cell_imag;
|
|
|
+ CELL *maskbuf;
|
|
|
|
|
|
int i, j; /* Loop control variables */
|
|
|
- int or, oc; /* Original dimensions of image */
|
|
|
- int rows, cols; /* Smallest powers of 2 >= number of rows & columns */
|
|
|
+ int rows, cols; /* number of rows & columns */
|
|
|
long totsize; /* Total number of data points */
|
|
|
- int halfrows, halfcols;
|
|
|
- double *data[2]; /* Data structure containing real & complex values of FFT */
|
|
|
- struct Option *op1, *op2, *op3;
|
|
|
- struct GModule *module;
|
|
|
+ double (*data)[2]; /* Data structure containing real & complex values of FFT */
|
|
|
|
|
|
G_gisinit(argv[0]);
|
|
|
|
|
@@ -51,188 +60,165 @@ int main(int argc, char *argv[])
|
|
|
_("Inverse Fast Fourier Transform (IFFT) for image processing.");
|
|
|
|
|
|
/* define options */
|
|
|
- op1 = G_define_option();
|
|
|
- op1->key = "real_image";
|
|
|
- op1->type = TYPE_STRING;
|
|
|
- op1->required = YES;
|
|
|
- op1->multiple = NO;
|
|
|
- op1->gisprompt = "old,cell,raster";
|
|
|
- op1->description = _("Input raster map (image fft, real part)");
|
|
|
-
|
|
|
- op2 = G_define_option();
|
|
|
- op2->key = "imaginary_image";
|
|
|
- op2->type = TYPE_STRING;
|
|
|
- op2->required = YES;
|
|
|
- op2->multiple = NO;
|
|
|
- op2->gisprompt = "old,cell,raster";
|
|
|
- op2->description = _("Input raster map (image fft, imaginary part");
|
|
|
-
|
|
|
- op3 = G_define_option();
|
|
|
- op3->key = "output_image";
|
|
|
- op3->type = TYPE_STRING;
|
|
|
- op3->required = YES;
|
|
|
- op3->multiple = NO;
|
|
|
- op3->gisprompt = "new,cell,raster";
|
|
|
- op3->description = _("Output inverse raster map after IFFT");
|
|
|
+ opt.real = G_define_option();
|
|
|
+ opt.real->key = "real_image";
|
|
|
+ opt.real->type = TYPE_STRING;
|
|
|
+ opt.real->required = YES;
|
|
|
+ opt.real->multiple = NO;
|
|
|
+ opt.real->gisprompt = "old,cell,raster";
|
|
|
+ opt.real->description = _("Input raster map (image fft, real part)");
|
|
|
+
|
|
|
+ opt.imag = G_define_option();
|
|
|
+ opt.imag->key = "imaginary_image";
|
|
|
+ opt.imag->type = TYPE_STRING;
|
|
|
+ opt.imag->required = YES;
|
|
|
+ opt.imag->multiple = NO;
|
|
|
+ opt.imag->gisprompt = "old,cell,raster";
|
|
|
+ opt.imag->description = _("Input raster map (image fft, imaginary part");
|
|
|
+
|
|
|
+ opt.orig = G_define_option();
|
|
|
+ opt.orig->key = "output_image";
|
|
|
+ opt.orig->type = TYPE_STRING;
|
|
|
+ opt.orig->required = YES;
|
|
|
+ opt.orig->multiple = NO;
|
|
|
+ opt.orig->gisprompt = "new,cell,raster";
|
|
|
+ opt.orig->description = _("Output inverse raster map after IFFT");
|
|
|
|
|
|
/*call parser */
|
|
|
if (G_parser(argc, argv))
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
- strcpy(Cellmap_real, op1->answer);
|
|
|
- strcpy(Cellmap_imag, op2->answer);
|
|
|
- strcpy(Cellmap_orig, op3->answer);
|
|
|
+ Cellmap_real = opt.real->answer;
|
|
|
+ Cellmap_imag = opt.imag->answer;
|
|
|
+ Cellmap_orig = opt.orig->answer;
|
|
|
|
|
|
/* open input raster map */
|
|
|
- if ((realmapset = G_find_cell(Cellmap_real, "")) == NULL)
|
|
|
- G_fatal_error(_("Unable to find the real-image map <%s>"),
|
|
|
- Cellmap_real);
|
|
|
-
|
|
|
- if ((realfp =
|
|
|
- G_fopen_old_misc("cell_misc", "fftreal", Cellmap_real,
|
|
|
- realmapset)) == NULL)
|
|
|
- G_fatal_error(_("Unable to open real-image in the cell_misc directory.\nInput map probably wasn't created by i.fft"));
|
|
|
+ realfd = G_open_cell_old(Cellmap_real, "");
|
|
|
+ if (realfd < 0)
|
|
|
+ G_fatal_error(_("Unable to open real input map <%s>"), Cellmap_real);
|
|
|
|
|
|
- if ((imagmapset = G_find_cell(Cellmap_imag, "")) == NULL)
|
|
|
- G_fatal_error(_("Unable to find the imaginary-image <%s>"),
|
|
|
- Cellmap_imag);
|
|
|
-
|
|
|
- if ((imagfp =
|
|
|
- G_fopen_old_misc("cell_misc", "fftimag", Cellmap_imag,
|
|
|
- imagmapset)) == NULL)
|
|
|
- G_fatal_error(_("Unable to open imaginary-image in the cell_misc directory.\nInput map probably wasn't created by i.fft"));
|
|
|
+ imagfd = G_open_cell_old(Cellmap_imag, "");
|
|
|
+ if (imagfd < 0)
|
|
|
+ G_fatal_error(_("Unable to open imaginary input map <%s>"), Cellmap_imag);
|
|
|
|
|
|
/* get and compare the original window data */
|
|
|
- get_orig_window(&orig_wind, realmapset, imagmapset);
|
|
|
+ G_get_cellhd(Cellmap_real, "", &realhead);
|
|
|
+ G_get_cellhd(Cellmap_imag, "", &imaghead);
|
|
|
+
|
|
|
+ if (realhead.proj != imaghead.proj ||
|
|
|
+ realhead.zone != imaghead.zone ||
|
|
|
+ realhead.north != imaghead.north ||
|
|
|
+ realhead.south != imaghead.south ||
|
|
|
+ realhead.east != imaghead.east ||
|
|
|
+ realhead.west != imaghead.west ||
|
|
|
+ realhead.ew_res != imaghead.ew_res ||
|
|
|
+ realhead.ns_res != imaghead.ns_res)
|
|
|
+ G_fatal_error(_("The real and imaginary original windows did not match."));
|
|
|
|
|
|
- or = orig_wind.rows;
|
|
|
- oc = orig_wind.cols;
|
|
|
- G_get_cellhd(Cellmap_real, realmapset, &realhead);
|
|
|
G_set_window(&realhead); /* set the window to the whole cell map */
|
|
|
|
|
|
/* get the rows and columns in the current window */
|
|
|
rows = G_window_rows();
|
|
|
cols = G_window_cols();
|
|
|
totsize = rows * cols;
|
|
|
- halfrows = rows / 2;
|
|
|
- halfcols = cols / 2;
|
|
|
-
|
|
|
- G_message(_("Power 2 values : [%d] rows [%d] columns."), rows, cols);
|
|
|
|
|
|
/* Allocate appropriate memory for the structure containing
|
|
|
the real and complex components of the FFT. DATA[0] will
|
|
|
contain the real, and DATA[1] the complex component.
|
|
|
*/
|
|
|
- data[0] = (double *)G_malloc((rows * cols) * sizeof(double));
|
|
|
- data[1] = (double *)G_malloc((rows * cols) * sizeof(double));
|
|
|
+ data = G_malloc(rows * cols * 2 * sizeof(double));
|
|
|
+
|
|
|
+ /* allocate the space for one row of cell map data */
|
|
|
+ cell_real = G_allocate_d_raster_buf();
|
|
|
+ cell_imag = G_allocate_d_raster_buf();
|
|
|
|
|
|
- /* Initialize real & complex components to zero */
|
|
|
+#define C(i, j) ((i) * cols + (j))
|
|
|
+
|
|
|
+ /* Read in cell map values */
|
|
|
G_message(_("Reading the raster maps..."));
|
|
|
- {
|
|
|
- fread((char *)data[0], sizeof(double), totsize, realfp);
|
|
|
- fread((char *)data[1], sizeof(double), totsize, imagfp);
|
|
|
+ for (i = 0; i < rows; i++) {
|
|
|
+ if (G_get_d_raster_row(realfd, cell_real, i) < 0)
|
|
|
+ G_fatal_error(_("Error while reading real input raster map."));
|
|
|
+ if (G_get_d_raster_row(imagfd, cell_imag, i) < 0)
|
|
|
+ G_fatal_error(_("Error while reading imaginary input raster map."));
|
|
|
+ for (j = 0; j < cols; j++) {
|
|
|
+ data[C(i, j)][0] = cell_real[j];
|
|
|
+ data[C(i, j)][1] = cell_imag[j];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ /* close input cell maps */
|
|
|
+ G_close_cell(realfd);
|
|
|
+ G_close_cell(imagfd);
|
|
|
+
|
|
|
/* Read in cell map values */
|
|
|
G_message(_("Masking the raster maps..."));
|
|
|
maskfd = G_maskfd();
|
|
|
- if (maskfd >= 0)
|
|
|
+ if (maskfd >= 0) {
|
|
|
maskbuf = G_allocate_cell_buf();
|
|
|
|
|
|
- if (maskfd >= 0) {
|
|
|
for (i = 0; i < rows; i++) {
|
|
|
- double *data0, *data1;
|
|
|
-
|
|
|
- data0 = data[0] + i * cols;
|
|
|
- data1 = data[1] + i * cols;
|
|
|
G_get_map_row(maskfd, maskbuf, i);
|
|
|
- for (j = 0; j < cols; j++, data0++, data1++) {
|
|
|
- if (maskbuf[j] == (CELL) 0) {
|
|
|
- *(data0) = 0.0;
|
|
|
- *(data1) = 0.0;
|
|
|
+ for (j = 0; j < cols; j++) {
|
|
|
+ if (maskbuf[j] == 0) {
|
|
|
+ data[C(i, j)][0] = 0.0;
|
|
|
+ data[C(i, j)][1] = 0.0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- G_message(_("Rotating data arrays..."));
|
|
|
- /* rotate the data array for standard display */
|
|
|
- for (i = 0; i < rows; i++) {
|
|
|
- double temp;
|
|
|
-
|
|
|
- for (j = 0; j < halfcols; j++) {
|
|
|
- temp = *(data[0] + i * cols + j);
|
|
|
- *(data[0] + i * cols + j) = *(data[0] + i * cols + j + halfcols);
|
|
|
- *(data[0] + i * cols + j + halfcols) = temp;
|
|
|
- temp = *(data[1] + i * cols + j);
|
|
|
- *(data[1] + i * cols + j) = *(data[1] + i * cols + j + halfcols);
|
|
|
- *(data[1] + i * cols + j + halfcols) = temp;
|
|
|
- }
|
|
|
+ G_close_cell(maskfd);
|
|
|
+ G_free(maskbuf);
|
|
|
}
|
|
|
- for (i = 0; i < halfrows; i++) {
|
|
|
- double temp;
|
|
|
|
|
|
- for (j = 0; j < cols; j++) {
|
|
|
- temp = *(data[0] + i * cols + j);
|
|
|
- *(data[0] + i * cols + j) =
|
|
|
- *(data[0] + (i + halfrows) * cols + j);
|
|
|
- *(data[0] + (i + halfrows) * cols + j) = temp;
|
|
|
- temp = *(data[1] + i * cols + j);
|
|
|
- *(data[1] + i * cols + j) =
|
|
|
- *(data[1] + (i + halfrows) * cols + j);
|
|
|
- *(data[1] + (i + halfrows) * cols + j) = temp;
|
|
|
- }
|
|
|
- }
|
|
|
+#define SWAP1(a, b) \
|
|
|
+ do { \
|
|
|
+ double temp = (a); \
|
|
|
+ (a) = (b); \
|
|
|
+ (b) = temp; \
|
|
|
+ } while (0)
|
|
|
|
|
|
+#define SWAP2(a, b) \
|
|
|
+ do { \
|
|
|
+ SWAP1(data[(a)][0], data[(b)][0]); \
|
|
|
+ SWAP1(data[(a)][1], data[(b)][1]); \
|
|
|
+ } while (0)
|
|
|
|
|
|
- /* close input cell maps and release the row buffers */
|
|
|
- fclose(realfp);
|
|
|
- fclose(imagfp);
|
|
|
- if (maskfd >= 0) {
|
|
|
- G_close_cell(maskfd);
|
|
|
- G_free(maskbuf);
|
|
|
- }
|
|
|
+ /* rotate the data array for standard display */
|
|
|
+ G_message(_("Rotating data arrays..."));
|
|
|
+ for (i = 0; i < rows; i++)
|
|
|
+ for (j = 0; j < cols / 2; j++)
|
|
|
+ SWAP2(C(i, j), C(i, j + cols / 2));
|
|
|
+ for (i = 0; i < rows / 2; i++)
|
|
|
+ for (j = 0; j < cols; j++)
|
|
|
+ SWAP2(C(i, j), C(i + rows / 2, j));
|
|
|
|
|
|
/* perform inverse FFT */
|
|
|
G_message(_("Starting Inverse FFT..."));
|
|
|
- fft(1, data, totsize, cols, rows);
|
|
|
+ fft2(1, data, totsize, cols, rows);
|
|
|
G_message(_("Inverse FFT completed..."));
|
|
|
|
|
|
- /* set up a window for the transform cell map */
|
|
|
- G_set_window(&orig_wind);
|
|
|
-
|
|
|
- /* open the output cell map and allocate a cell row buffer */
|
|
|
- if ((outputfd = G_open_cell_new(Cellmap_orig)) < 0)
|
|
|
- G_fatal_error(_("Unable to open output file."));
|
|
|
-
|
|
|
- cell_row = G_allocate_cell_buf();
|
|
|
+ /* open the output cell map */
|
|
|
+ if ((outputfd = G_open_fp_cell_new(Cellmap_orig)) < 0)
|
|
|
+ G_fatal_error(_("Unable to open output map <%s>"), Cellmap_orig);
|
|
|
|
|
|
/* Write out result to a new cell map */
|
|
|
- G_message(_("Writing data to file..."));
|
|
|
- for (i = 0; i < or; i++) {
|
|
|
- for (j = 0; j < oc; j++) {
|
|
|
- *(cell_row + j) = (CELL) (*(data[0] + i * cols + j) + 0.5);
|
|
|
- }
|
|
|
- G_put_raster_row(outputfd, cell_row, CELL_TYPE);
|
|
|
+ G_message(_("Writing output map..."));
|
|
|
+ for (i = 0; i < rows; i++) {
|
|
|
+ for (j = 0; j < cols; j++)
|
|
|
+ cell_real[j] = data[C(i, j)][0];
|
|
|
+ G_put_d_raster_row(outputfd, cell_real);
|
|
|
}
|
|
|
+
|
|
|
G_close_cell(outputfd);
|
|
|
|
|
|
- G_free(cell_row);
|
|
|
- {
|
|
|
- struct Colors colors;
|
|
|
- struct Range range;
|
|
|
- CELL min, max;
|
|
|
-
|
|
|
- /* make a real component color table */
|
|
|
- G_read_range(Cellmap_orig, G_mapset(), &range);
|
|
|
- G_get_range_min_max(&range, &min, &max);
|
|
|
- G_make_grey_scale_colors(&colors, min, max);
|
|
|
- G_write_colors(Cellmap_orig, G_mapset(), &colors);
|
|
|
- }
|
|
|
+ G_free(cell_real);
|
|
|
+ G_free(cell_imag);
|
|
|
+
|
|
|
+ fft_colors(Cellmap_orig);
|
|
|
|
|
|
/* Release memory resources */
|
|
|
- G_free(data[0]);
|
|
|
- G_free(data[1]);
|
|
|
+ G_free(data);
|
|
|
|
|
|
G_done_msg(_("Transform successful."));
|
|
|
|