|
@@ -1,3 +1,4 @@
|
|
|
|
+
|
|
/***************************************************************************
|
|
/***************************************************************************
|
|
atcorr - atmospheric correction for Grass GIS
|
|
atcorr - atmospheric correction for Grass GIS
|
|
|
|
|
|
@@ -29,40 +30,51 @@
|
|
|
|
|
|
* Addition of IRS-1C LISS, Feb 2009: Markus Neteler
|
|
* Addition of IRS-1C LISS, Feb 2009: Markus Neteler
|
|
|
|
|
|
-TODO: use dynamic allocation for TiCache
|
|
|
|
|
|
+* input elevation/visibility map: efficient cache with dynamic memory
|
|
|
|
+* allocation: Markus Metz, Apr 2011
|
|
|
|
+
|
|
***************************************************************************/
|
|
***************************************************************************/
|
|
|
|
|
|
#include <cstdlib>
|
|
#include <cstdlib>
|
|
#include <map>
|
|
#include <map>
|
|
|
|
|
|
-extern "C" {
|
|
|
|
|
|
+extern "C"
|
|
|
|
+{
|
|
#include <grass/gis.h>
|
|
#include <grass/gis.h>
|
|
#include <grass/raster.h>
|
|
#include <grass/raster.h>
|
|
#include <grass/glocale.h>
|
|
#include <grass/glocale.h>
|
|
|
|
+#include <grass/rbtree.h>
|
|
}
|
|
}
|
|
|
|
|
|
#include "Transform.h"
|
|
#include "Transform.h"
|
|
#include "6s.h"
|
|
#include "6s.h"
|
|
|
|
|
|
|
|
+/* TICache: create 1 meter bins for altitude in km */
|
|
|
|
+/* 10m bins are also ok */
|
|
|
|
+/* BIN_ALT = 1000 / <bin size in meters> */
|
|
|
|
+#define BIN_ALT 1000.
|
|
|
|
+/* TICache: create 1 km bins for visibility */
|
|
|
|
+#define BIN_VIS 1.
|
|
|
|
+
|
|
/* Input options and flags */
|
|
/* Input options and flags */
|
|
struct Options
|
|
struct Options
|
|
{
|
|
{
|
|
/* options */
|
|
/* options */
|
|
- struct Option *iimg; /* input satellite image */
|
|
|
|
- struct Option *iscl; /* input data is scaled to this range */
|
|
|
|
- struct Option *ialt; /* an input elevation map in km used to increase */
|
|
|
|
- /* atmospheric correction accuracy, including this */
|
|
|
|
- /* will make computations take much, much longer */
|
|
|
|
- struct Option *ivis; /* an input visibility map in km (same purpose and effect as ialt) */
|
|
|
|
- struct Option *icnd; /* the input conditions file */
|
|
|
|
- struct Option *oimg; /* output image name */
|
|
|
|
- struct Option *oscl; /* scale the output data (reflectance values) to this range */
|
|
|
|
|
|
+ struct Option *iimg; /* input satellite image */
|
|
|
|
+ struct Option *iscl; /* input data is scaled to this range */
|
|
|
|
+ struct Option *ialt; /* an input elevation map in meters used to increase */
|
|
|
|
+ /* atmospheric correction accuracy, including this */
|
|
|
|
+ /* will make computations take much, much longer */
|
|
|
|
+ struct Option *ivis; /* an input visibility map in km (same purpose and effect as ialt) */
|
|
|
|
+ struct Option *icnd; /* the input conditions file */
|
|
|
|
+ struct Option *oimg; /* output image name */
|
|
|
|
+ struct Option *oscl; /* scale the output data (reflectance values) to this range */
|
|
|
|
|
|
/* flags */
|
|
/* flags */
|
|
- struct Flag *oflt; /* output data as floating point and do not round */
|
|
|
|
- struct Flag *irad; /* treat input values as reflectance instead of radiance values */
|
|
|
|
- struct Flag *etmafter; /* treat input data as a satelite image of type etm+ taken after July 1, 2000 */
|
|
|
|
- struct Flag *etmbefore; /* treat input data as a satelite image of type etm+ taken before July 1, 2000 */
|
|
|
|
|
|
+ struct Flag *oflt; /* output data as floating point and do not round */
|
|
|
|
+ struct Flag *irad; /* treat input values as reflectance instead of radiance values */
|
|
|
|
+ struct Flag *etmafter; /* treat input data as a satelite image of type etm+ taken after July 1, 2000 */
|
|
|
|
+ struct Flag *etmbefore; /* treat input data as a satelite image of type etm+ taken before July 1, 2000 */
|
|
struct Flag *optimize;
|
|
struct Flag *optimize;
|
|
};
|
|
};
|
|
|
|
|
|
@@ -72,16 +84,20 @@ struct ScaleRange
|
|
int max;
|
|
int max;
|
|
};
|
|
};
|
|
|
|
|
|
-
|
|
|
|
-int hit = 0;
|
|
|
|
-int mis = 0;
|
|
|
|
|
|
+struct RBitem
|
|
|
|
+{
|
|
|
|
+ int alt; /* elevation */
|
|
|
|
+ int vis; /* visibility */
|
|
|
|
+ TransformInput ti; /* transformation parameters */
|
|
|
|
+};
|
|
|
|
|
|
/* function prototypes */
|
|
/* function prototypes */
|
|
static void adjust_region(const char *);
|
|
static void adjust_region(const char *);
|
|
static CELL round_c(FCELL);
|
|
static CELL round_c(FCELL);
|
|
static void write_fp_to_cell(int, FCELL *);
|
|
static void write_fp_to_cell(int, FCELL *);
|
|
-static void process_raster(int, InputMask, ScaleRange, int, int, int, bool, ScaleRange, bool);
|
|
|
|
-static void copy_colors(char *, const char *, char *);
|
|
|
|
|
|
+static void process_raster(int, InputMask, ScaleRange, int, int, int, bool,
|
|
|
|
+ ScaleRange, bool);
|
|
|
|
+static void copy_colors(const char *, char *);
|
|
static void define_module(void);
|
|
static void define_module(void);
|
|
static struct Options define_options(void);
|
|
static struct Options define_options(void);
|
|
static void read_scale(Option *, ScaleRange &);
|
|
static void read_scale(Option *, ScaleRange &);
|
|
@@ -91,7 +107,7 @@ static void read_scale(Option *, ScaleRange &);
|
|
Adjust the region to that of the input raster.
|
|
Adjust the region to that of the input raster.
|
|
Atmospheric corrections should be done on the whole
|
|
Atmospheric corrections should be done on the whole
|
|
satelite image, not just portions.
|
|
satelite image, not just portions.
|
|
-*/
|
|
|
|
|
|
+ */
|
|
static void adjust_region(const char *name)
|
|
static void adjust_region(const char *name)
|
|
{
|
|
{
|
|
struct Cell_head iimg_head; /* the input image header file */
|
|
struct Cell_head iimg_head; /* the input image header file */
|
|
@@ -105,157 +121,108 @@ static void adjust_region(const char *name)
|
|
/* Rounds a floating point cell value */
|
|
/* Rounds a floating point cell value */
|
|
static CELL round_c(FCELL x)
|
|
static CELL round_c(FCELL x)
|
|
{
|
|
{
|
|
- if(x >= 0.0)
|
|
|
|
- return (CELL)(x + .5);
|
|
|
|
|
|
+ if (x >= 0.0)
|
|
|
|
+ return (CELL) (x + .5);
|
|
|
|
|
|
- return (CELL)(-(-x + .5));
|
|
|
|
|
|
+ return (CELL) (-(-x + .5));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Converts the buffer to cell and write it to disk */
|
|
/* Converts the buffer to cell and write it to disk */
|
|
-static void write_fp_to_cell(int ofd, FCELL* buf)
|
|
|
|
|
|
+static void write_fp_to_cell(int ofd, FCELL *buf)
|
|
{
|
|
{
|
|
- CELL* cbuf;
|
|
|
|
|
|
+ CELL *cbuf;
|
|
int col;
|
|
int col;
|
|
|
|
|
|
- cbuf = (CELL*)Rast_allocate_buf(CELL_TYPE);
|
|
|
|
|
|
+ cbuf = (CELL *) Rast_allocate_buf(CELL_TYPE);
|
|
|
|
|
|
- for(col = 0; col < Rast_window_cols(); col++) cbuf[col] = round_c(buf[col]);
|
|
|
|
|
|
+ for (col = 0; col < Rast_window_cols(); col++)
|
|
|
|
+ cbuf[col] = round_c(buf[col]);
|
|
Rast_put_row(ofd, cbuf, CELL_TYPE);
|
|
Rast_put_row(ofd, cbuf, CELL_TYPE);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-/* See also Cache note below */
|
|
|
|
-class TICache
|
|
|
|
|
|
+/* compare function for RB tree */
|
|
|
|
+static int compare_hv(const void *ti_a, const void *ti_b)
|
|
{
|
|
{
|
|
- enum TICacheSize
|
|
|
|
- {
|
|
|
|
- MAX_TIs = 4096 /* this value is a guess, increase it if in general
|
|
|
|
- * more categories are used. TODO: use dynamic allocation
|
|
|
|
- * since 4096 is the limit on 32bit */
|
|
|
|
- };
|
|
|
|
- TransformInput tis[MAX_TIs];
|
|
|
|
- float alts[MAX_TIs];
|
|
|
|
- int p;
|
|
|
|
-
|
|
|
|
-public:
|
|
|
|
- TICache() { p = 0; for(int i = 0; i < MAX_TIs; i++) alts[i] = -1; }
|
|
|
|
- int search(float alt) {
|
|
|
|
- for(int i = 0; i < MAX_TIs; i++)
|
|
|
|
- if(alt == alts[i])
|
|
|
|
- {
|
|
|
|
- hit++;
|
|
|
|
- return i;
|
|
|
|
- }
|
|
|
|
- mis++;
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- TransformInput get(int i) { return tis[i]; }
|
|
|
|
- void add(TransformInput ti, float alt) {
|
|
|
|
- tis[p] = ti;
|
|
|
|
- alts[p] = alt;
|
|
|
|
- p++;
|
|
|
|
- if(p >= MAX_TIs) p = 0;
|
|
|
|
|
|
+ struct RBitem *a, *b;
|
|
|
|
+
|
|
|
|
+ a = (struct RBitem *)ti_a;
|
|
|
|
+ b = (struct RBitem *)ti_b;
|
|
|
|
+
|
|
|
|
+ /* check most common case first
|
|
|
|
+ * also faster if either an altitude or a visibility map is given,
|
|
|
|
+ * but not both */
|
|
|
|
+ if (a->alt == b->alt) {
|
|
|
|
+ if (a->vis == b->vis)
|
|
|
|
+ return 0;
|
|
|
|
+ if (a->vis > b->vis)
|
|
|
|
+ return 1;
|
|
|
|
+ else if (a->vis < b->vis)
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
-};
|
|
|
|
|
|
+ else if (a->alt > b->alt)
|
|
|
|
+ return 1;
|
|
|
|
+ else if (a->alt < b->alt)
|
|
|
|
+ return -1;
|
|
|
|
|
|
|
|
+ /* should not be reached */
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
|
|
-/* the transform input map, is a array of ticaches.
|
|
|
|
- The first key is the visibility which matches to a TICache for the altitudes.
|
|
|
|
- This code is horrible, i just spent 20min writing and 5min debugging it. */
|
|
|
|
-
|
|
|
|
-/* Cache note:
|
|
|
|
- The DEM cases are in range 0 < DEM < 8888 for the World in case of using an
|
|
|
|
- integer DEM values in meters. So the cache should ideally store 8888 different
|
|
|
|
- cases for the World-type conditions if all happen in the same image. */
|
|
|
|
-
|
|
|
|
-class TIMap
|
|
|
|
|
|
+/* Cache for transformation input parameters */
|
|
|
|
+class TICache
|
|
{
|
|
{
|
|
- enum TIMapSize
|
|
|
|
- {
|
|
|
|
- MAX_TICs = 4096 /* this value is a guess. It means that <size> TI's will be
|
|
|
|
- * the max combinations of vis/alt pairs. TODO: use dynamic allocation
|
|
|
|
- * since 4096 is the limit on 32bit */
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- TICache tic[MAX_TICs]; /* array of TICaches */
|
|
|
|
- float visi[MAX_TICs];
|
|
|
|
- int p;
|
|
|
|
|
|
+ struct RB_TREE *RBTree;
|
|
|
|
+ unsigned int tree_size;
|
|
|
|
|
|
-public:
|
|
|
|
- struct Position
|
|
|
|
|
|
+ private:
|
|
|
|
+ struct RBitem set_alt_vis(float alt, float vis)
|
|
{
|
|
{
|
|
- int i, j;
|
|
|
|
- Position() : i(-1), j(-1) {}
|
|
|
|
- Position(int x, int y) : i(x), j(y) {}
|
|
|
|
- bool valid() { return i != -1 && j != -1; }
|
|
|
|
- };
|
|
|
|
|
|
+ struct RBitem rbitem;
|
|
|
|
+
|
|
|
|
+ /* although alt and vis are already rounded,
|
|
|
|
+ * the + 0.5 is needed for fp representation errors */
|
|
|
|
+ /* alt has been converted to kilometers */
|
|
|
|
+ rbitem.alt = (int) (alt * BIN_ALT + 0.5);
|
|
|
|
+ /* vis should be kilometers */
|
|
|
|
+ rbitem.vis = (int) (vis + 0.5);
|
|
|
|
|
|
- TIMap() { p = 0; for(int i = 0; i < MAX_TICs; i++) visi[i] = -1; }
|
|
|
|
- Position search(float vis, float alt) {
|
|
|
|
- for(int i = 0; i < MAX_TICs; i++)
|
|
|
|
- if(vis == visi[i]) {
|
|
|
|
- Position pos;
|
|
|
|
- pos.i = i;
|
|
|
|
- pos.j = tic[i].search(alt);
|
|
|
|
- return pos;
|
|
|
|
- }
|
|
|
|
- return Position();
|
|
|
|
|
|
+ return rbitem;
|
|
}
|
|
}
|
|
|
|
|
|
- TransformInput get(Position pos) { return tic[pos.i].get(pos.j); }
|
|
|
|
-
|
|
|
|
- void add(TransformInput ti, float vis, float alt) {
|
|
|
|
- tic[p].add(ti, alt);
|
|
|
|
- visi[p] = vis;
|
|
|
|
- p++;
|
|
|
|
- if(p >= MAX_TICs) p = 0;
|
|
|
|
|
|
+ public:
|
|
|
|
+ TICache()
|
|
|
|
+ {
|
|
|
|
+ RBTree = rbtree_create(compare_hv, sizeof(struct RBitem));
|
|
|
|
+ tree_size = 0;
|
|
}
|
|
}
|
|
-};
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-struct IntPair
|
|
|
|
-{
|
|
|
|
- FCELL x;
|
|
|
|
- FCELL y;
|
|
|
|
-
|
|
|
|
- IntPair(FCELL i, FCELL j) : x(i), y(j) {}
|
|
|
|
-
|
|
|
|
- bool operator<(const IntPair& b) const
|
|
|
|
- {
|
|
|
|
- if(x < b.x) return true;
|
|
|
|
- else if(x > b.x) return false;
|
|
|
|
- else if(y < b.y) return true;
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-};
|
|
|
|
|
|
+ int search(float alt, float vis, TransformInput *ti)
|
|
|
|
+ {
|
|
|
|
+ struct RBitem search_ti = set_alt_vis(alt, vis);
|
|
|
|
+ struct RBitem *found_ti;
|
|
|
|
|
|
|
|
+ found_ti = (struct RBitem *)rbtree_find(RBTree, &search_ti);
|
|
|
|
+ if (found_ti) {
|
|
|
|
+ *ti = found_ti->ti;
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ return 0;
|
|
|
|
|
|
-typedef std::map<IntPair, TransformInput> CacheMap;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ void add(TransformInput ti, float alt, float vis)
|
|
|
|
+ {
|
|
|
|
+ struct RBitem insert_ti = set_alt_vis(alt, vis);
|
|
|
|
|
|
-const TransformInput& optimize_va(const FCELL& vis, const FCELL& alt)
|
|
|
|
-{
|
|
|
|
- static CacheMap timap;
|
|
|
|
- static TransformInput ti;
|
|
|
|
|
|
+ /* add safety check here */
|
|
|
|
+ tree_size++;
|
|
|
|
|
|
- IntPair key(vis, alt);
|
|
|
|
- CacheMap::iterator it = timap.find(key);
|
|
|
|
|
|
+ insert_ti.ti = ti;
|
|
|
|
|
|
- if(it != timap.end()) /* search found key */
|
|
|
|
- {
|
|
|
|
- ti = (*it).second;
|
|
|
|
|
|
+ rbtree_insert(RBTree, &insert_ti);
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- pre_compute_hv(alt, vis);
|
|
|
|
- ti = compute();
|
|
|
|
- timap.insert(std::make_pair(key, ti));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ti;
|
|
|
|
-}
|
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
|
|
/* Process the raster and do atmospheric corrections.
|
|
/* Process the raster and do atmospheric corrections.
|
|
@@ -271,140 +238,167 @@ const TransformInput& optimize_va(const FCELL& vis, const FCELL& alt)
|
|
ofd: output file descriptor
|
|
ofd: output file descriptor
|
|
oflt: if true use FCELL_TYPE for output
|
|
oflt: if true use FCELL_TYPE for output
|
|
oscale: output file's range (default is min = 0, max = 255)
|
|
oscale: output file's range (default is min = 0, max = 255)
|
|
-*/
|
|
|
|
|
|
+ */
|
|
static void process_raster(int ifd, InputMask imask, ScaleRange iscale,
|
|
static void process_raster(int ifd, InputMask imask, ScaleRange iscale,
|
|
- int ialt_fd, int ivis_fd, int ofd, bool oflt,
|
|
|
|
- ScaleRange oscale, bool optimize)
|
|
|
|
|
|
+ int ialt_fd, int ivis_fd, int ofd, bool oflt,
|
|
|
|
+ ScaleRange oscale, bool optimize)
|
|
{
|
|
{
|
|
- FCELL* buf; /* buffer for the input values */
|
|
|
|
- FCELL* alt = NULL; /* buffer for the elevation values */
|
|
|
|
- FCELL* vis = NULL; /* buffer for the visibility values */
|
|
|
|
- FCELL prev_alt = -1.f;
|
|
|
|
- FCELL prev_vis = -1.f;
|
|
|
|
|
|
+ FCELL *buf; /* buffer for the input values */
|
|
|
|
+ FCELL *alt = NULL; /* buffer for the elevation values */
|
|
|
|
+ FCELL *vis = NULL; /* buffer for the visibility values */
|
|
|
|
+ FCELL prev_alt = -1.f;
|
|
|
|
+ FCELL prev_vis = -1.f;
|
|
int row, col, nrows, ncols;
|
|
int row, col, nrows, ncols;
|
|
|
|
|
|
/* do initial computation with global elevation and visibility values */
|
|
/* do initial computation with global elevation and visibility values */
|
|
TransformInput ti;
|
|
TransformInput ti;
|
|
|
|
+
|
|
ti = compute();
|
|
ti = compute();
|
|
|
|
|
|
- TICache ticache; /* use this to increase computation speed when an elevation map with categories are given */
|
|
|
|
-
|
|
|
|
|
|
+ /* use a cache to increase computation speed when an elevation map
|
|
|
|
+ * and/or a visibility map is given */
|
|
|
|
+ TICache ticache;
|
|
|
|
+
|
|
/* allocate memory for buffers */
|
|
/* allocate memory for buffers */
|
|
- buf = (FCELL*)Rast_allocate_buf(FCELL_TYPE);
|
|
|
|
- if(ialt_fd >= 0) alt = (FCELL*)Rast_allocate_buf(FCELL_TYPE);
|
|
|
|
- if(ivis_fd >= 0) vis = (FCELL*)Rast_allocate_buf(FCELL_TYPE);
|
|
|
|
|
|
+ buf = (FCELL *) Rast_allocate_buf(FCELL_TYPE);
|
|
|
|
+ if (ialt_fd >= 0)
|
|
|
|
+ alt = (FCELL *) Rast_allocate_buf(FCELL_TYPE);
|
|
|
|
+ if (ivis_fd >= 0)
|
|
|
|
+ vis = (FCELL *) Rast_allocate_buf(FCELL_TYPE);
|
|
|
|
|
|
nrows = Rast_window_rows();
|
|
nrows = Rast_window_rows();
|
|
ncols = Rast_window_cols();
|
|
ncols = Rast_window_cols();
|
|
|
|
|
|
- for(row = 0; row < nrows; row++)
|
|
|
|
- {
|
|
|
|
- G_percent(row, nrows, 1); /* keep the user informed of our progress */
|
|
|
|
-
|
|
|
|
- /* read the next row */
|
|
|
|
|
|
+ for (row = 0; row < nrows; row++) {
|
|
|
|
+ G_percent(row, nrows, 1); /* keep the user informed of our progress */
|
|
|
|
+
|
|
|
|
+ /* read the next row */
|
|
Rast_get_row(ifd, buf, row, FCELL_TYPE);
|
|
Rast_get_row(ifd, buf, row, FCELL_TYPE);
|
|
|
|
|
|
- /* read the next row of elevation values */
|
|
|
|
- if(ialt_fd >= 0)
|
|
|
|
|
|
+ /* read the next row of elevation values */
|
|
|
|
+ if (ialt_fd >= 0)
|
|
Rast_get_row(ialt_fd, alt, row, FCELL_TYPE);
|
|
Rast_get_row(ialt_fd, alt, row, FCELL_TYPE);
|
|
|
|
|
|
- /* read the next row of elevation values */
|
|
|
|
- if(ivis_fd >= 0)
|
|
|
|
|
|
+ /* read the next row of elevation values */
|
|
|
|
+ if (ivis_fd >= 0)
|
|
Rast_get_row(ivis_fd, vis, row, FCELL_TYPE);
|
|
Rast_get_row(ivis_fd, vis, row, FCELL_TYPE);
|
|
|
|
|
|
- /* loop over all the values in the row */
|
|
|
|
- for(col = 0; col < ncols; col++)
|
|
|
|
- {
|
|
|
|
- if((vis && Rast_is_f_null_value(&vis[col])) ||
|
|
|
|
- (alt && Rast_is_f_null_value(&alt[col])) ||
|
|
|
|
- Rast_is_f_null_value(&buf[col]))
|
|
|
|
- {
|
|
|
|
- Rast_set_f_null_value(&buf[col], 1);
|
|
|
|
- continue;
|
|
|
|
|
|
+ /* loop over all the values in the row */
|
|
|
|
+ for (col = 0; col < ncols; col++) {
|
|
|
|
+ if ((vis && Rast_is_f_null_value(&vis[col])) ||
|
|
|
|
+ (alt && Rast_is_f_null_value(&alt[col])) ||
|
|
|
|
+ Rast_is_f_null_value(&buf[col])) {
|
|
|
|
+ Rast_set_f_null_value(&buf[col], 1);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if (ialt_fd >= 0) {
|
|
|
|
+ if (alt[col] < 0)
|
|
|
|
+ alt[col] = 0; /* on or below sea level, all the same for 6S */
|
|
|
|
+ else
|
|
|
|
+ alt[col] /= 1000.0f; /* converting to km from input which should be in meter */
|
|
|
|
+
|
|
|
|
+ /* round to nearest altitude bin */
|
|
|
|
+ /* rounding result: watch out for fp representation error */
|
|
|
|
+ alt[col] = ((int) (alt[col] * BIN_ALT + 0.5)) / BIN_ALT;
|
|
|
|
+ }
|
|
|
|
+ if (ivis_fd >= 0) {
|
|
|
|
+ if (vis[col] < 0)
|
|
|
|
+ vis[col] = 0; /* negative visibility is invalid, print a WARNING ? */
|
|
|
|
+
|
|
|
|
+ /* round to nearest visibility bin */
|
|
|
|
+ /* rounding result: watch out for fp representation error */
|
|
|
|
+ vis[col] = ((int) (vis[col] + 0.5));
|
|
}
|
|
}
|
|
- if (ialt_fd >= 0)
|
|
|
|
- alt[col] /= 1000.0f; /* converting to km from input which should be in meter */
|
|
|
|
-
|
|
|
|
- /* check if both maps are active and if whether any value has changed */
|
|
|
|
- if((ialt_fd >= 0) && (ivis_fd >= 0) && ((prev_vis != vis[col]) || (prev_alt != alt[col])))
|
|
|
|
- {
|
|
|
|
- prev_alt = alt[col]; /* update new values */
|
|
|
|
- prev_vis = vis[col];
|
|
|
|
- if(optimize) ti = optimize_va(vis[col], alt[col]); /* try to optimize? */
|
|
|
|
- else { /* no optimizations */
|
|
|
|
- pre_compute_hv(alt[col], vis[col]);
|
|
|
|
- ti = compute();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else /* only one of the maps is being used */
|
|
|
|
- {
|
|
|
|
- if((ivis_fd >= 0) && (prev_vis != vis[col]))
|
|
|
|
- {
|
|
|
|
- prev_vis = vis[col]; /* keep track of previous visibility */
|
|
|
|
-
|
|
|
|
- if(optimize)
|
|
|
|
- {
|
|
|
|
- int p = ticache.search(vis[col]);
|
|
|
|
- if(p >= 0) ti = ticache.get(p);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- pre_compute_v(vis[col]); /* re-compute transformation inputs */
|
|
|
|
- ti = compute(); /* ... */
|
|
|
|
-
|
|
|
|
- ticache.add(ti, vis[col]);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- pre_compute_v(vis[col]); /* re-compute transformation inputs */
|
|
|
|
- ti = compute(); /* ... */
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if((ialt_fd >= 0) && (prev_alt != alt[col]))
|
|
|
|
- {
|
|
|
|
- prev_alt = alt[col]; /* keep track of previous altitude */
|
|
|
|
-
|
|
|
|
- if(optimize)
|
|
|
|
- {
|
|
|
|
- int p = ticache.search(alt[col]);
|
|
|
|
- if(p >= 0) ti = ticache.get(p);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- pre_compute_h(alt[col]); /* re-compute transformation inputs */
|
|
|
|
- ti = compute(); /* ... */
|
|
|
|
-
|
|
|
|
- ticache.add(ti, alt[col]);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- pre_compute_h(alt[col]); /* re-compute transformation inputs */
|
|
|
|
- ti = compute(); /* ... */
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- G_debug(3, "Computed r%d (%d), c%d (%d)", row, nrows, col, ncols);
|
|
|
|
- /* transform from iscale.[min,max] to [0,1] */
|
|
|
|
- buf[col] = (buf[col] - iscale.min) / ((float)iscale.max - (float)iscale.min);
|
|
|
|
- buf[col] = transform(ti, imask, buf[col]);
|
|
|
|
- /* transform from [0,1] to oscale.[min,max] */
|
|
|
|
- buf[col] = buf[col] * ((float)oscale.max - (float)oscale.min) + oscale.min;
|
|
|
|
|
|
|
|
- if(~oflt && (buf[col] > (float)oscale.max))
|
|
|
|
|
|
+ /* check if both maps are active and if whether any value has changed */
|
|
|
|
+ if ((ialt_fd >= 0) && (ivis_fd >= 0) &&
|
|
|
|
+ ((prev_vis != vis[col]) || (prev_alt != alt[col]))) {
|
|
|
|
+ prev_alt = alt[col]; /* update new values */
|
|
|
|
+ prev_vis = vis[col];
|
|
|
|
+ if (optimize) {
|
|
|
|
+ int in_cache = ticache.search(alt[col], vis[col], &ti);
|
|
|
|
+
|
|
|
|
+ if (!in_cache) {
|
|
|
|
+ pre_compute_hv(alt[col], vis[col]); /* re-compute transformation inputs */
|
|
|
|
+ ti = compute(); /* ... */
|
|
|
|
+
|
|
|
|
+ ticache.add(ti, alt[col], vis[col]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ pre_compute_hv(alt[col], vis[col]); /* re-compute transformation inputs */
|
|
|
|
+ ti = compute(); /* ... */
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else { /* only one of the maps is being used */
|
|
|
|
+
|
|
|
|
+ if ((ivis_fd >= 0) && (prev_vis != vis[col])) {
|
|
|
|
+ prev_vis = vis[col]; /* keep track of previous visibility */
|
|
|
|
+
|
|
|
|
+ if (optimize) {
|
|
|
|
+ int in_cache = ticache.search(0, vis[col], &ti);
|
|
|
|
+
|
|
|
|
+ if (!in_cache) {
|
|
|
|
+ pre_compute_v(vis[col]); /* re-compute transformation inputs */
|
|
|
|
+ ti = compute(); /* ... */
|
|
|
|
+
|
|
|
|
+ ticache.add(ti, 0, vis[col]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ pre_compute_v(vis[col]); /* re-compute transformation inputs */
|
|
|
|
+ ti = compute(); /* ... */
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((ialt_fd >= 0) && (prev_alt != alt[col])) {
|
|
|
|
+ prev_alt = alt[col]; /* keep track of previous altitude */
|
|
|
|
+
|
|
|
|
+ if (optimize) {
|
|
|
|
+ int in_cache = ticache.search(alt[col], 0, &ti);
|
|
|
|
+
|
|
|
|
+ if (!in_cache) {
|
|
|
|
+ pre_compute_h(alt[col]); /* re-compute transformation inputs */
|
|
|
|
+ ti = compute(); /* ... */
|
|
|
|
+
|
|
|
|
+ ticache.add(ti, alt[col], 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ pre_compute_h(alt[col]); /* re-compute transformation inputs */
|
|
|
|
+ ti = compute(); /* ... */
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ G_debug(3, "Computed r%d (%d), c%d (%d)", row, nrows, col, ncols);
|
|
|
|
+ /* transform from iscale.[min,max] to [0,1] */
|
|
|
|
+ buf[col] =
|
|
|
|
+ (buf[col] - iscale.min) / ((float)iscale.max -
|
|
|
|
+ (float)iscale.min);
|
|
|
|
+ buf[col] = transform(ti, imask, buf[col]);
|
|
|
|
+ /* transform from [0,1] to oscale.[min,max] */
|
|
|
|
+ buf[col] =
|
|
|
|
+ buf[col] * ((float)oscale.max - (float)oscale.min) +
|
|
|
|
+ oscale.min;
|
|
|
|
+
|
|
|
|
+ if (~oflt && (buf[col] > (float)oscale.max))
|
|
G_warning(_("The output data will overflow. Reflectance > 100%%"));
|
|
G_warning(_("The output data will overflow. Reflectance > 100%%"));
|
|
}
|
|
}
|
|
|
|
|
|
- /* write output */
|
|
|
|
- if(oflt) Rast_put_row(ofd, buf, FCELL_TYPE);
|
|
|
|
- else write_fp_to_cell(ofd, buf);
|
|
|
|
|
|
+ /* write output */
|
|
|
|
+ if (oflt)
|
|
|
|
+ Rast_put_row(ofd, buf, FCELL_TYPE);
|
|
|
|
+ else
|
|
|
|
+ write_fp_to_cell(ofd, buf);
|
|
}
|
|
}
|
|
G_percent(1, 1, 1);
|
|
G_percent(1, 1, 1);
|
|
-
|
|
|
|
|
|
+
|
|
/* free allocated memory */
|
|
/* free allocated memory */
|
|
G_free(buf);
|
|
G_free(buf);
|
|
- if(ialt_fd >= 0) G_free(alt);
|
|
|
|
- if(ivis_fd >= 0) G_free(vis);
|
|
|
|
|
|
+ if (ialt_fd >= 0)
|
|
|
|
+ G_free(alt);
|
|
|
|
+ if (ivis_fd >= 0)
|
|
|
|
+ G_free(vis);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -425,7 +419,8 @@ static void define_module(void)
|
|
struct GModule *module;
|
|
struct GModule *module;
|
|
|
|
|
|
module = G_define_module();
|
|
module = G_define_module();
|
|
- module->label = _("Performs atmospheric correction using the 6S algorithm.");
|
|
|
|
|
|
+ module->label =
|
|
|
|
+ _("Performs atmospheric correction using the 6S algorithm.");
|
|
module->description =
|
|
module->description =
|
|
_("6S - Second Simulation of Satellite Signal in the Solar Spectrum.");
|
|
_("6S - Second Simulation of Satellite Signal in the Solar Spectrum.");
|
|
G_add_keyword(_("imagery"));
|
|
G_add_keyword(_("imagery"));
|
|
@@ -446,7 +441,7 @@ static void define_module(void)
|
|
" The code is provided as is and is not to be sold. See notes on\n"
|
|
" The code is provided as is and is not to be sold. See notes on\n"
|
|
" http://loasys.univ-lille1.fr/informatique/sixs_gb.html\n"
|
|
" http://loasys.univ-lille1.fr/informatique/sixs_gb.html\n"
|
|
" http://www.ltid.inpe.br/dsr/mauro/6s/index.html\n"
|
|
" http://www.ltid.inpe.br/dsr/mauro/6s/index.html\n"
|
|
- " and on http://www.cs.sun.ac.za/~caz/index.html\n";*/
|
|
|
|
|
|
+ " and on http://www.cs.sun.ac.za/~caz/index.html\n"; */
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -456,41 +451,41 @@ static struct Options define_options(void)
|
|
struct Options opts;
|
|
struct Options opts;
|
|
|
|
|
|
opts.iimg = G_define_standard_option(G_OPT_R_INPUT);
|
|
opts.iimg = G_define_standard_option(G_OPT_R_INPUT);
|
|
-
|
|
|
|
|
|
+
|
|
opts.iscl = G_define_option();
|
|
opts.iscl = G_define_option();
|
|
- opts.iscl->key = "range";
|
|
|
|
- opts.iscl->type = TYPE_INTEGER;
|
|
|
|
- opts.iscl->key_desc = "min,max";
|
|
|
|
- opts.iscl->required = NO;
|
|
|
|
- opts.iscl->answer = "0,255";
|
|
|
|
- opts.iscl->description = _("Input range");
|
|
|
|
|
|
+ opts.iscl->key = "range";
|
|
|
|
+ opts.iscl->type = TYPE_INTEGER;
|
|
|
|
+ opts.iscl->key_desc = "min,max";
|
|
|
|
+ opts.iscl->required = NO;
|
|
|
|
+ opts.iscl->answer = "0,255";
|
|
|
|
+ opts.iscl->description = _("Input range");
|
|
opts.iscl->guisection = _("Input");
|
|
opts.iscl->guisection = _("Input");
|
|
|
|
|
|
opts.ialt = G_define_standard_option(G_OPT_R_ELEV);
|
|
opts.ialt = G_define_standard_option(G_OPT_R_ELEV);
|
|
- opts.ialt->required = NO;
|
|
|
|
- opts.ialt->description = _("Name of input elevation raster map (in m)");
|
|
|
|
- opts.ialt->guisection = _("Input");
|
|
|
|
|
|
+ opts.ialt->required = NO;
|
|
|
|
+ opts.ialt->description = _("Name of input elevation raster map (in m)");
|
|
|
|
+ opts.ialt->guisection = _("Input");
|
|
|
|
|
|
opts.ivis = G_define_standard_option(G_OPT_R_INPUT);
|
|
opts.ivis = G_define_standard_option(G_OPT_R_INPUT);
|
|
- opts.ivis->key = "visibility";
|
|
|
|
- opts.ivis->required = NO;
|
|
|
|
- opts.ivis->description = _("Name of input visibility raster map (in km)");
|
|
|
|
- opts.ivis->guisection = _("Input");
|
|
|
|
|
|
+ opts.ivis->key = "visibility";
|
|
|
|
+ opts.ivis->required = NO;
|
|
|
|
+ opts.ivis->description = _("Name of input visibility raster map (in km)");
|
|
|
|
+ opts.ivis->guisection = _("Input");
|
|
|
|
|
|
opts.icnd = G_define_standard_option(G_OPT_F_INPUT);
|
|
opts.icnd = G_define_standard_option(G_OPT_F_INPUT);
|
|
- opts.icnd->key = "parameters";
|
|
|
|
- opts.icnd->required = YES;
|
|
|
|
- opts.icnd->description = _("Name of input text file with 6S parameters");
|
|
|
|
|
|
+ opts.icnd->key = "parameters";
|
|
|
|
+ opts.icnd->required = YES;
|
|
|
|
+ opts.icnd->description = _("Name of input text file with 6S parameters");
|
|
|
|
|
|
opts.oimg = G_define_standard_option(G_OPT_R_OUTPUT);
|
|
opts.oimg = G_define_standard_option(G_OPT_R_OUTPUT);
|
|
|
|
|
|
opts.oscl = G_define_option();
|
|
opts.oscl = G_define_option();
|
|
- opts.oscl->key = "rescale";
|
|
|
|
- opts.oscl->type = TYPE_INTEGER;
|
|
|
|
- opts.oscl->key_desc = "min,max";
|
|
|
|
- opts.oscl->answer = "0,255";
|
|
|
|
- opts.oscl->required = NO;
|
|
|
|
- opts.oscl->description = _("Rescale output raster map");
|
|
|
|
|
|
+ opts.oscl->key = "rescale";
|
|
|
|
+ opts.oscl->type = TYPE_INTEGER;
|
|
|
|
+ opts.oscl->key_desc = "min,max";
|
|
|
|
+ opts.oscl->answer = "0,255";
|
|
|
|
+ opts.oscl->required = NO;
|
|
|
|
+ opts.oscl->description = _("Rescale output raster map");
|
|
opts.oscl->guisection = _("Output");
|
|
opts.oscl->guisection = _("Output");
|
|
|
|
|
|
opts.oflt = G_define_flag();
|
|
opts.oflt = G_define_flag();
|
|
@@ -500,111 +495,112 @@ static struct Options define_options(void)
|
|
|
|
|
|
opts.irad = G_define_flag();
|
|
opts.irad = G_define_flag();
|
|
opts.irad->key = 'r';
|
|
opts.irad->key = 'r';
|
|
- opts.irad->description = _("Input raster map converted to reflectance (default is radiance)");
|
|
|
|
|
|
+ opts.irad->description =
|
|
|
|
+ _("Input raster map converted to reflectance (default is radiance)");
|
|
opts.irad->guisection = _("Input");
|
|
opts.irad->guisection = _("Input");
|
|
|
|
|
|
opts.etmafter = G_define_flag();
|
|
opts.etmafter = G_define_flag();
|
|
opts.etmafter->key = 'a';
|
|
opts.etmafter->key = 'a';
|
|
- opts.etmafter->description = _("Input from ETM+ image taken after July 1, 2000");
|
|
|
|
|
|
+ opts.etmafter->description =
|
|
|
|
+ _("Input from ETM+ image taken after July 1, 2000");
|
|
opts.etmafter->guisection = _("Input");
|
|
opts.etmafter->guisection = _("Input");
|
|
|
|
|
|
opts.etmbefore = G_define_flag();
|
|
opts.etmbefore = G_define_flag();
|
|
opts.etmbefore->key = 'b';
|
|
opts.etmbefore->key = 'b';
|
|
- opts.etmbefore->description = _("Input from ETM+ image taken before July 1, 2000");
|
|
|
|
|
|
+ opts.etmbefore->description =
|
|
|
|
+ _("Input from ETM+ image taken before July 1, 2000");
|
|
opts.etmbefore->guisection = _("Input");
|
|
opts.etmbefore->guisection = _("Input");
|
|
|
|
|
|
opts.optimize = G_define_flag();
|
|
opts.optimize = G_define_flag();
|
|
opts.optimize->key = 'o';
|
|
opts.optimize->key = 'o';
|
|
- opts.optimize->description = _("Try to increase computation speed when categorized altitude or/and visibility map is used");
|
|
|
|
|
|
+ opts.optimize->description =
|
|
|
|
+ _("Try to increase computation speed when altitude and/or visibility map is used");
|
|
|
|
|
|
return opts;
|
|
return opts;
|
|
}
|
|
}
|
|
|
|
|
|
/* Read the min and max values from the iscl and oscl options */
|
|
/* Read the min and max values from the iscl and oscl options */
|
|
-void read_scale(Option *scl, ScaleRange &range)
|
|
|
|
|
|
+void read_scale(Option * scl, ScaleRange & range)
|
|
{
|
|
{
|
|
/* set default values */
|
|
/* set default values */
|
|
range.min = 0;
|
|
range.min = 0;
|
|
range.max = 255;
|
|
range.max = 255;
|
|
|
|
|
|
- if(scl->answer)
|
|
|
|
- {
|
|
|
|
- sscanf(scl->answers[0], "%d", &range.min);
|
|
|
|
- sscanf(scl->answers[1], "%d", &range.max);
|
|
|
|
|
|
+ if (scl->answer) {
|
|
|
|
+ sscanf(scl->answers[0], "%d", &range.min);
|
|
|
|
+ sscanf(scl->answers[1], "%d", &range.max);
|
|
|
|
|
|
- if(range.min==range.max)
|
|
|
|
- {
|
|
|
|
- G_warning(_("Scale range length should be > 0; Using default values: [0,255]"));
|
|
|
|
|
|
+ if (range.min == range.max) {
|
|
|
|
+ G_warning(_("Scale range length should be > 0; Using default values: [0,255]"));
|
|
|
|
|
|
- range.min = 0;
|
|
|
|
- range.max = 255;
|
|
|
|
- }
|
|
|
|
|
|
+ range.min = 0;
|
|
|
|
+ range.max = 255;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* swap values if max is smaller than min */
|
|
/* swap values if max is smaller than min */
|
|
- if(range.max < range.min)
|
|
|
|
- {
|
|
|
|
- int temp;
|
|
|
|
- temp = range.max;
|
|
|
|
- range.max = range.min;
|
|
|
|
- range.min = temp;
|
|
|
|
|
|
+ if (range.max < range.min) {
|
|
|
|
+ int temp;
|
|
|
|
+
|
|
|
|
+ temp = range.max;
|
|
|
|
+ range.max = range.min;
|
|
|
|
+ range.min = temp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-int main(int argc, char* argv[])
|
|
|
|
|
|
+int main(int argc, char *argv[])
|
|
{
|
|
{
|
|
- struct Options opts;
|
|
|
|
- struct ScaleRange iscale; /* input file's data is scaled to this interval */
|
|
|
|
- struct ScaleRange oscale; /* output file's scale */
|
|
|
|
- int iimg_fd; /* input image's file descriptor */
|
|
|
|
- int oimg_fd; /* output image's file descriptor */
|
|
|
|
- int ialt_fd = -1; /* input elevation map's file descriptor */
|
|
|
|
- int ivis_fd = -1; /* input visibility map's file descriptor */
|
|
|
|
|
|
+ struct Options opts;
|
|
|
|
+ struct ScaleRange iscale; /* input file's data is scaled to this interval */
|
|
|
|
+ struct ScaleRange oscale; /* output file's scale */
|
|
|
|
+ int iimg_fd; /* input image's file descriptor */
|
|
|
|
+ int oimg_fd; /* output image's file descriptor */
|
|
|
|
+ int ialt_fd = -1; /* input elevation map's file descriptor */
|
|
|
|
+ int ivis_fd = -1; /* input visibility map's file descriptor */
|
|
struct History hist;
|
|
struct History hist;
|
|
-
|
|
|
|
|
|
+ struct Cell_head orig_window;
|
|
|
|
+
|
|
/* Define module */
|
|
/* Define module */
|
|
define_module();
|
|
define_module();
|
|
-
|
|
|
|
|
|
+
|
|
/* Define the different input options */
|
|
/* Define the different input options */
|
|
opts = define_options();
|
|
opts = define_options();
|
|
|
|
|
|
/**** Start ****/
|
|
/**** Start ****/
|
|
G_gisinit(argv[0]);
|
|
G_gisinit(argv[0]);
|
|
- if(G_parser(argc, argv) < 0)
|
|
|
|
|
|
+ if (G_parser(argc, argv) < 0)
|
|
exit(EXIT_FAILURE);
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
|
|
+ G_get_set_window(&orig_window);
|
|
adjust_region(opts.iimg->answer);
|
|
adjust_region(opts.iimg->answer);
|
|
|
|
|
|
/* open input raster */
|
|
/* open input raster */
|
|
- if((iimg_fd = Rast_open_old(opts.iimg->answer, "")) < 0)
|
|
|
|
- G_fatal_error(_("Unable to open raster map <%s>"),
|
|
|
|
- opts.iimg->answer);
|
|
|
|
-
|
|
|
|
- if(opts.ialt->answer) {
|
|
|
|
- if((ialt_fd = Rast_open_old(opts.ialt->answer, "")) < 0)
|
|
|
|
- G_fatal_error(_("Unable to open raster map <%s>"),
|
|
|
|
- opts.ialt->answer);
|
|
|
|
|
|
+ if ((iimg_fd = Rast_open_old(opts.iimg->answer, "")) < 0)
|
|
|
|
+ G_fatal_error(_("Unable to open raster map <%s>"), opts.iimg->answer);
|
|
|
|
+
|
|
|
|
+ if (opts.ialt->answer) {
|
|
|
|
+ if ((ialt_fd = Rast_open_old(opts.ialt->answer, "")) < 0)
|
|
|
|
+ G_fatal_error(_("Unable to open raster map <%s>"),
|
|
|
|
+ opts.ialt->answer);
|
|
}
|
|
}
|
|
|
|
|
|
- if(opts.ivis->answer) {
|
|
|
|
- if((ivis_fd = Rast_open_old(opts.ivis->answer, "")) < 0)
|
|
|
|
- G_fatal_error(_("Unable to open raster map <%s>"),
|
|
|
|
- opts.ivis->answer);
|
|
|
|
|
|
+ if (opts.ivis->answer) {
|
|
|
|
+ if ((ivis_fd = Rast_open_old(opts.ivis->answer, "")) < 0)
|
|
|
|
+ G_fatal_error(_("Unable to open raster map <%s>"),
|
|
|
|
+ opts.ivis->answer);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/* open a floating point raster or not? */
|
|
/* open a floating point raster or not? */
|
|
- if(opts.oflt->answer)
|
|
|
|
- {
|
|
|
|
- if((oimg_fd = Rast_open_fp_new(opts.oimg->answer)) < 0)
|
|
|
|
|
|
+ if (opts.oflt->answer) {
|
|
|
|
+ if ((oimg_fd = Rast_open_fp_new(opts.oimg->answer)) < 0)
|
|
G_fatal_error(_("Unable to create raster map <%s>"),
|
|
G_fatal_error(_("Unable to create raster map <%s>"),
|
|
- opts.oimg->answer);
|
|
|
|
|
|
+ opts.oimg->answer);
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- if((oimg_fd = Rast_open_new(opts.oimg->answer, CELL_TYPE)) < 0)
|
|
|
|
|
|
+ else {
|
|
|
|
+ if ((oimg_fd = Rast_open_new(opts.oimg->answer, CELL_TYPE)) < 0)
|
|
G_fatal_error(_("Unable to create raster map <%s>"),
|
|
G_fatal_error(_("Unable to create raster map <%s>"),
|
|
- opts.oimg->answer);
|
|
|
|
|
|
+ opts.oimg->answer);
|
|
}
|
|
}
|
|
|
|
|
|
/* read the scale parameters */
|
|
/* read the scale parameters */
|
|
@@ -613,24 +609,37 @@ int main(int argc, char* argv[])
|
|
|
|
|
|
/* initialize this 6s computation and parse the input conditions file */
|
|
/* initialize this 6s computation and parse the input conditions file */
|
|
init_6S(opts.icnd->answer);
|
|
init_6S(opts.icnd->answer);
|
|
-
|
|
|
|
- InputMask imask = RADIANCE; /* the input mask tells us what transformations if any
|
|
|
|
- needs to be done to make our input values, reflectance
|
|
|
|
- values scaled between 0 and 1 */
|
|
|
|
- if(opts.irad->answer) imask = REFLECTANCE;
|
|
|
|
- if(opts.etmbefore->answer) imask = (InputMask)(imask | ETM_BEFORE);
|
|
|
|
- if(opts.etmafter->answer) imask = (InputMask)(imask | ETM_AFTER);
|
|
|
|
|
|
+
|
|
|
|
+ InputMask imask = RADIANCE; /* the input mask tells us what transformations if any
|
|
|
|
+ needs to be done to make our input values, reflectance
|
|
|
|
+ values scaled between 0 and 1 */
|
|
|
|
+ if (opts.irad->answer)
|
|
|
|
+ imask = REFLECTANCE;
|
|
|
|
+ if (opts.etmbefore->answer)
|
|
|
|
+ imask = (InputMask) (imask | ETM_BEFORE);
|
|
|
|
+ if (opts.etmafter->answer)
|
|
|
|
+ imask = (InputMask) (imask | ETM_AFTER);
|
|
|
|
+
|
|
|
|
+ if ((ialt_fd >= 0 || ivis_fd >= 0) && !opts.optimize->answer) {
|
|
|
|
+ G_message(_("An elevation and/or visibility map is given, but the optimization flag is not set."));
|
|
|
|
+ G_message(_("This can take some time."));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* switch on optimization automatically if elevation and/or visibility map is given? */
|
|
|
|
|
|
/* process the input raster and produce our atmospheric corrected output raster. */
|
|
/* process the input raster and produce our atmospheric corrected output raster. */
|
|
|
|
+ G_message(_("Atmospheric correction..."));
|
|
process_raster(iimg_fd, imask, iscale, ialt_fd, ivis_fd,
|
|
process_raster(iimg_fd, imask, iscale, ialt_fd, ivis_fd,
|
|
- oimg_fd, opts.oflt->answer, oscale, opts.optimize->answer);
|
|
|
|
|
|
+ oimg_fd, opts.oflt->answer, oscale, opts.optimize->answer);
|
|
|
|
|
|
|
|
|
|
/* Close the input and output file descriptors */
|
|
/* Close the input and output file descriptors */
|
|
Rast_short_history(opts.oimg->answer, "raster", &hist);
|
|
Rast_short_history(opts.oimg->answer, "raster", &hist);
|
|
Rast_close(iimg_fd);
|
|
Rast_close(iimg_fd);
|
|
- if(opts.ialt->answer) Rast_close(ialt_fd);
|
|
|
|
- if(opts.ivis->answer) Rast_close(ivis_fd);
|
|
|
|
|
|
+ if (opts.ialt->answer)
|
|
|
|
+ Rast_close(ialt_fd);
|
|
|
|
+ if (opts.ivis->answer)
|
|
|
|
+ Rast_close(ivis_fd);
|
|
Rast_close(oimg_fd);
|
|
Rast_close(oimg_fd);
|
|
|
|
|
|
Rast_command_history(&hist);
|
|
Rast_command_history(&hist);
|
|
@@ -640,5 +649,8 @@ int main(int argc, char* argv[])
|
|
Scaling is ignored and color ranges might not be correct. */
|
|
Scaling is ignored and color ranges might not be correct. */
|
|
copy_colors(opts.iimg->answer, opts.oimg->answer);
|
|
copy_colors(opts.iimg->answer, opts.oimg->answer);
|
|
|
|
|
|
|
|
+ Rast_set_window(&orig_window);
|
|
|
|
+ G_message(_("Atmospheric correction complete."));
|
|
|
|
+
|
|
exit(EXIT_SUCCESS);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
}
|