|
@@ -3,11 +3,11 @@
|
|
|
*
|
|
|
* MODULE: r.out.gdal
|
|
|
* AUTHOR(S): Vytautas Vebra <olivership@gmail.com>
|
|
|
-* PURPOSE: exports GRASS raster to many GDAL suported formats;
|
|
|
+* PURPOSE: Exports GRASS raster to GDAL suported formats;
|
|
|
* based on GDAL library.
|
|
|
-* Replace r.out.gdal.sh script based on gdal_translate
|
|
|
-* executable.
|
|
|
-* COPYRIGHT: (C) 2006-2007 by the GRASS Development Team
|
|
|
+* Replaces r.out.gdal.sh script which used the gdal_translate
|
|
|
+* executable and GDAL grass-format plugin.
|
|
|
+* COPYRIGHT: (C) 2006-2008 by the GRASS Development Team
|
|
|
*
|
|
|
* This program is free software under the GNU General Public
|
|
|
* License (>=v2). Read the file COPYING that comes with GRASS
|
|
@@ -31,8 +31,8 @@
|
|
|
|
|
|
#include "cpl_string.h"
|
|
|
#include "gdal.h"
|
|
|
+#include "local_proto.h"
|
|
|
|
|
|
-#define GRASS_MAX_COLORS 100000 /* what is the right value ? */
|
|
|
|
|
|
void supported_formats(char **formats)
|
|
|
{
|
|
@@ -81,274 +81,6 @@ void supported_formats(char **formats)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-int import_band(GDALDatasetH hMEMDS, int band, const char *name,
|
|
|
- const char *mapset, struct Cell_head *cellhead,
|
|
|
- RASTER_MAP_TYPE maptype, double nodataval,
|
|
|
- const char *nodatakey)
|
|
|
-{
|
|
|
-
|
|
|
- struct Colors sGrassColors;
|
|
|
- GDALColorTableH hCT;
|
|
|
- int iColor;
|
|
|
- int bHaveMinMax;
|
|
|
- double dfCellMin;
|
|
|
- double dfCellMax;
|
|
|
- struct FPRange sRange;
|
|
|
- int fd;
|
|
|
- int cols = cellhead->cols;
|
|
|
- int rows = cellhead->rows;
|
|
|
-
|
|
|
- /* Open GRASS raster */
|
|
|
- fd = G_open_cell_old(name, mapset);
|
|
|
- if (fd < 0) {
|
|
|
- G_warning(_("Unable to open raster map <%s>"), name);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* Get raster band */
|
|
|
- GDALRasterBandH hBand = GDALGetRasterBand(hMEMDS, band);
|
|
|
-
|
|
|
- if (hBand == NULL) {
|
|
|
- G_warning(_("Unable to get raster band"));
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* Get min/max values. */
|
|
|
- if (G_read_fp_range(name, mapset, &sRange) == -1) {
|
|
|
- bHaveMinMax = FALSE;
|
|
|
- }
|
|
|
- else {
|
|
|
- bHaveMinMax = TRUE;
|
|
|
- G_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax);
|
|
|
- }
|
|
|
-
|
|
|
- /* suppress useless warnings */
|
|
|
- CPLPushErrorHandler(CPLQuietErrorHandler);
|
|
|
- GDALSetRasterColorInterpretation(hBand, GPI_RGB);
|
|
|
- CPLPopErrorHandler();
|
|
|
-
|
|
|
- if (G_read_colors(name, mapset, &sGrassColors) >= 0) {
|
|
|
- int maxcolor, i;
|
|
|
- CELL min, max;
|
|
|
- char key[200], value[200];
|
|
|
- int rcount;
|
|
|
-
|
|
|
- G_get_color_range(&min, &max, &sGrassColors);
|
|
|
- if (bHaveMinMax) {
|
|
|
- if (max < dfCellMax) {
|
|
|
- maxcolor = max;
|
|
|
- }
|
|
|
- else {
|
|
|
- maxcolor = (int)ceil(dfCellMax);
|
|
|
- }
|
|
|
- if (maxcolor > GRASS_MAX_COLORS) {
|
|
|
- maxcolor = GRASS_MAX_COLORS;
|
|
|
- G_warning("Too many values, color table cut to %d entries",
|
|
|
- maxcolor);
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- if (max < GRASS_MAX_COLORS) {
|
|
|
- maxcolor = max;
|
|
|
- }
|
|
|
- else {
|
|
|
- maxcolor = GRASS_MAX_COLORS;
|
|
|
- G_warning("Too many values, color table set to %d entries",
|
|
|
- maxcolor);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- rcount = G_colors_count(&sGrassColors);
|
|
|
-
|
|
|
- G_debug(3, "dfCellMin: %f, dfCellMax: %f, maxcolor: %d", dfCellMin,
|
|
|
- dfCellMax, maxcolor);
|
|
|
-
|
|
|
- hCT = GDALCreateColorTable(GPI_RGB);
|
|
|
- for (iColor = 0; iColor <= maxcolor; iColor++) {
|
|
|
- int nRed, nGreen, nBlue;
|
|
|
- GDALColorEntry sColor;
|
|
|
-
|
|
|
- if (G_get_color(iColor, &nRed, &nGreen, &nBlue, &sGrassColors)) {
|
|
|
- sColor.c1 = nRed;
|
|
|
- sColor.c2 = nGreen;
|
|
|
- sColor.c3 = nBlue;
|
|
|
- sColor.c4 = 255;
|
|
|
-
|
|
|
- G_debug(3,
|
|
|
- "G_get_color: Y, rcount %d, nRed %d, nGreen %d, nBlue %d",
|
|
|
- rcount, nRed, nGreen, nBlue);
|
|
|
- GDALSetColorEntry(hCT, iColor, &sColor);
|
|
|
- }
|
|
|
- else {
|
|
|
- sColor.c1 = 0;
|
|
|
- sColor.c2 = 0;
|
|
|
- sColor.c3 = 0;
|
|
|
- sColor.c4 = 0;
|
|
|
-
|
|
|
- G_debug(3,
|
|
|
- "G_get_color: N, rcount %d, nRed %d, nGreen %d, nBlue %d",
|
|
|
- rcount, nRed, nGreen, nBlue);
|
|
|
- GDALSetColorEntry(hCT, iColor, &sColor);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (rcount > 0) {
|
|
|
- /* Create metadata entries for color table rules */
|
|
|
- sprintf(value, "%d", rcount);
|
|
|
- GDALSetMetadataItem(hBand, "COLOR_TABLE_RULES_COUNT", value,
|
|
|
- NULL);
|
|
|
- }
|
|
|
-
|
|
|
- /* Add the rules in reverse order */
|
|
|
- for (i = rcount - 1; i >= 0; i--) {
|
|
|
- DCELL val1, val2;
|
|
|
- unsigned char r1, g1, b1, r2, g2, b2;
|
|
|
-
|
|
|
- G_get_f_color_rule(&val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2,
|
|
|
- &sGrassColors, i);
|
|
|
-
|
|
|
-
|
|
|
- sprintf(key, "COLOR_TABLE_RULE_RGB_%d", rcount - i - 1);
|
|
|
- sprintf(value, "%e %e %d %d %d %d %d %d", val1, val2, r1, g1, b1,
|
|
|
- r2, g2, b2);
|
|
|
- GDALSetMetadataItem(hBand, key, value, NULL);
|
|
|
- }
|
|
|
- GDALSetRasterColorTable(hBand, hCT);
|
|
|
- }
|
|
|
- else {
|
|
|
- hCT = GDALCreateColorTable(GPI_RGB);
|
|
|
- GDALSetMetadataItem(hBand, "COLOR_TABLE_RULES_COUNT", "0", NULL);
|
|
|
- GDALSetRasterColorTable(hBand, hCT);
|
|
|
- }
|
|
|
-
|
|
|
- /* Create GRASS raster buffer */
|
|
|
- void *bufer = G_allocate_raster_buf(maptype);
|
|
|
-
|
|
|
- if (bufer == NULL) {
|
|
|
- G_warning(_("Unable to allocate buffer for reading raster map"));
|
|
|
- return -1;
|
|
|
- }
|
|
|
- char *nulls = (char *)G_malloc(cols);
|
|
|
-
|
|
|
- if (nulls == NULL) {
|
|
|
- G_warning(_("Unable to allocate buffer for reading raster map"));
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* Copy data form GRASS raster to memory raster */
|
|
|
- int row, col;
|
|
|
- int n_nulls = 0;
|
|
|
-
|
|
|
- if (maptype == FCELL_TYPE) {
|
|
|
-
|
|
|
- /* Source datatype understandible by GDAL */
|
|
|
- GDALDataType datatype = GDT_Float32;
|
|
|
- FCELL fnullval = (FCELL) nodataval;
|
|
|
-
|
|
|
- for (row = 0; row < rows; row++) {
|
|
|
-
|
|
|
- if (G_get_raster_row(fd, bufer, row, maptype) < 0) {
|
|
|
- G_warning(_("Unable to read raster map <%s> row %d"),
|
|
|
- name, row);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- G_get_null_value_row(fd, nulls, row);
|
|
|
- for (col = 0; col < cols; col++)
|
|
|
- if (nulls[col]) {
|
|
|
- ((FCELL *) bufer)[col] = fnullval;
|
|
|
- if (n_nulls == 0) {
|
|
|
- GDALSetRasterNoDataValue(hBand, nodataval);
|
|
|
- }
|
|
|
- n_nulls++;
|
|
|
- }
|
|
|
-
|
|
|
- if (GDALRasterIO
|
|
|
- (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype,
|
|
|
- 0, 0) >= CE_Failure) {
|
|
|
- G_warning(_("Unable to write GDAL raster file"));
|
|
|
- return -1;
|
|
|
- }
|
|
|
- G_percent(row + 1, rows, 2);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (maptype == DCELL_TYPE) {
|
|
|
-
|
|
|
- GDALDataType datatype = GDT_Float64;
|
|
|
- DCELL dnullval = (DCELL) nodataval;
|
|
|
-
|
|
|
- for (row = 0; row < rows; row++) {
|
|
|
-
|
|
|
- if (G_get_raster_row(fd, bufer, row, maptype) < 0) {
|
|
|
- G_warning(_("Unable to read raster map <%s> row %d"),
|
|
|
- name, row);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- G_get_null_value_row(fd, nulls, row);
|
|
|
- for (col = 0; col < cols; col++)
|
|
|
- if (nulls[col]) {
|
|
|
- ((DCELL *) bufer)[col] = dnullval;
|
|
|
- if (n_nulls == 0) {
|
|
|
- GDALSetRasterNoDataValue(hBand, nodataval);
|
|
|
- }
|
|
|
- n_nulls++;
|
|
|
- }
|
|
|
-
|
|
|
- if (GDALRasterIO
|
|
|
- (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype,
|
|
|
- 0, 0) >= CE_Failure) {
|
|
|
- G_warning(_("Unable to write GDAL raster file"));
|
|
|
- return -1;
|
|
|
- }
|
|
|
- G_percent(row + 1, rows, 2);
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- GDALDataType datatype = GDT_Int32;
|
|
|
- CELL inullval = (CELL) nodataval;
|
|
|
-
|
|
|
- for (row = 0; row < rows; row++) {
|
|
|
-
|
|
|
- if (G_get_raster_row(fd, bufer, row, maptype) < 0) {
|
|
|
- G_warning(_("Unable to read raster map <%s> row %d"),
|
|
|
- name, row);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- G_get_null_value_row(fd, nulls, row);
|
|
|
- for (col = 0; col < cols; col++)
|
|
|
- if (nulls[col]) {
|
|
|
- ((CELL *) bufer)[col] = inullval;
|
|
|
- if (n_nulls == 0) {
|
|
|
- GDALSetRasterNoDataValue(hBand, nodataval);
|
|
|
- }
|
|
|
- n_nulls++;
|
|
|
- }
|
|
|
-
|
|
|
- if (GDALRasterIO
|
|
|
- (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype,
|
|
|
- 0, 0) >= CE_Failure) {
|
|
|
- G_warning(_("Unable to write GDAL raster file"));
|
|
|
- return -1;
|
|
|
- }
|
|
|
- G_percent(row + 1, rows, 2);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (n_nulls > 0) { /* TODO: && nodata_param NOT specified */
|
|
|
- if (maptype == CELL_TYPE)
|
|
|
- G_warning(_("Input raster map contains cells with NULL-value (no-data). "
|
|
|
- "The value %d was used to represent no-data values in the input map. "
|
|
|
- "You can specify nodata value by %s parameter."),
|
|
|
- (int)nodataval, nodatakey);
|
|
|
- else
|
|
|
- G_warning(_("Input raster map contains cells with NULL-value (no-data). "
|
|
|
- "The value %g was used to represent no-data values in the input map. "
|
|
|
- "You can specify nodata value by %s parameter."),
|
|
|
- nodataval, nodatakey);
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
|
|
|
static void AttachMetadata(GDALDatasetH hDS, char **papszMetadataOptions)
|
|
|
/* function taken from gdal_translate */
|
|
@@ -373,7 +105,7 @@ int main(int argc, char *argv[])
|
|
|
{
|
|
|
|
|
|
struct GModule *module;
|
|
|
- struct Flag *flag_l;
|
|
|
+ struct Flag *flag_l, *flag_c;
|
|
|
struct Option *input, *format, *type, *output, *createopt, *metaopt,
|
|
|
*nodataopt;
|
|
|
|
|
@@ -390,7 +122,7 @@ int main(int argc, char *argv[])
|
|
|
|
|
|
module = G_define_module();
|
|
|
module->description =
|
|
|
- _("Exports GRASS raster map into GDAL supported formats.");
|
|
|
+ _("Exports GRASS raster maps into GDAL supported formats.");
|
|
|
module->keywords = _("raster, export");
|
|
|
|
|
|
flag_l = G_define_flag();
|
|
@@ -398,6 +130,11 @@ int main(int argc, char *argv[])
|
|
|
flag_l->description = _("List supported output formats");
|
|
|
flag_l->guisection = _("Print");
|
|
|
|
|
|
+ flag_c = G_define_flag();
|
|
|
+ flag_c->key = 'c';
|
|
|
+ flag_c->label = _("Do not export long colortable");
|
|
|
+ flag_c->description = _("Only applicable to Byte or UInt16 data types.");
|
|
|
+
|
|
|
input = G_define_standard_option(G_OPT_R_INPUT);
|
|
|
input->required = NO;
|
|
|
input->description = _("Name of raster map (or group) to export");
|
|
@@ -430,7 +167,7 @@ int main(int argc, char *argv[])
|
|
|
type->type = TYPE_STRING;
|
|
|
type->description = _("File type");
|
|
|
type->options =
|
|
|
- "Byte,Int16,UInt16,UInt32,Int32,Float32,Float64,CInt16,CInt32,CFloat32,CFloat64";
|
|
|
+ "Byte,Int16,UInt16,Int32,UInt32,Float32,Float64,CInt16,CInt32,CFloat32,CFloat64";
|
|
|
type->required = NO;
|
|
|
|
|
|
output = G_define_standard_option(G_OPT_R_OUTPUT);
|
|
@@ -442,8 +179,8 @@ int main(int argc, char *argv[])
|
|
|
createopt = G_define_option();
|
|
|
createopt->key = "createopt";
|
|
|
createopt->type = TYPE_STRING;
|
|
|
- createopt->description = _("Creation option to the output format driver. "
|
|
|
- "Multiple options may be listed.");
|
|
|
+ createopt->description =
|
|
|
+ _("Creation option(s) to pass to the output format driver");
|
|
|
createopt->multiple = YES;
|
|
|
createopt->required = NO;
|
|
|
|
|
@@ -463,9 +200,11 @@ int main(int argc, char *argv[])
|
|
|
nodataopt->multiple = NO;
|
|
|
nodataopt->required = NO;
|
|
|
|
|
|
+
|
|
|
if (G_parser(argc, argv))
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
+
|
|
|
#ifndef __ALLOW_DYNAMIC_OPTIONS__
|
|
|
/* Init GDAL */
|
|
|
GDALAllRegister();
|
|
@@ -476,9 +215,8 @@ int main(int argc, char *argv[])
|
|
|
exit(EXIT_SUCCESS);
|
|
|
}
|
|
|
|
|
|
- if (!input->answer) {
|
|
|
+ if (!input->answer)
|
|
|
G_fatal_error(_("Required parameter <%s> not set"), input->key);
|
|
|
- }
|
|
|
|
|
|
/* Try to open input GRASS raster.. */
|
|
|
mapset = G_find_cell2(input->answer, "");
|
|
@@ -633,7 +371,7 @@ int main(int argc, char *argv[])
|
|
|
nodataval = (double)(short)0x8000;
|
|
|
}
|
|
|
else {
|
|
|
- datatype = GDT_Int32; /* need to furthermore fine tune this? */
|
|
|
+ datatype = GDT_Int32; /* need to fine tune this more? */
|
|
|
nodataval = (double)(int)0x80000000;
|
|
|
}
|
|
|
}
|
|
@@ -645,6 +383,11 @@ int main(int argc, char *argv[])
|
|
|
nodataval = atof(nodataopt->answer);
|
|
|
}
|
|
|
|
|
|
+/* TODO:
|
|
|
+ if( nodata_used && nodataval is out_of_type_range )
|
|
|
+ G_fatal_error(_("No-data value out of range for type %s"), type->answer);
|
|
|
+*/
|
|
|
+
|
|
|
G_debug(3, "Input map datatype=%s\n",
|
|
|
(maptype == CELL_TYPE ? "CELL" :
|
|
|
(maptype == DCELL_TYPE ? "DCELL" :
|
|
@@ -722,9 +465,9 @@ int main(int argc, char *argv[])
|
|
|
ref.file[band].mapset),
|
|
|
band + 1);
|
|
|
}
|
|
|
- if (import_band
|
|
|
+ if (export_band
|
|
|
(hCurrDS, band + 1, ref.file[band].name, ref.file[band].mapset,
|
|
|
- &cellhead, maptype, nodataval, nodataopt->key) < 0)
|
|
|
+ &cellhead, maptype, nodataval, nodataopt->key, flag_c->answer) < 0)
|
|
|
G_warning(_("Unable to export raster map <%s>"),
|
|
|
ref.file[band].name);
|
|
|
}
|
|
@@ -740,12 +483,12 @@ int main(int argc, char *argv[])
|
|
|
}
|
|
|
|
|
|
GDALClose(hDstDS);
|
|
|
+
|
|
|
if (hMEMDS)
|
|
|
GDALClose(hMEMDS);
|
|
|
|
|
|
CSLDestroy(papszOptions);
|
|
|
|
|
|
G_done_msg(" ");
|
|
|
-
|
|
|
exit(EXIT_SUCCESS);
|
|
|
}
|