[GRASS-SVN] r36750 - grass/trunk/raster/r.out.gdal

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Apr 16 07:18:13 EDT 2009


Author: mmetz
Date: 2009-04-16 07:18:13 -0400 (Thu, 16 Apr 2009)
New Revision: 36750

Modified:
   grass/trunk/raster/r.out.gdal/export_band.c
   grass/trunk/raster/r.out.gdal/local_proto.h
   grass/trunk/raster/r.out.gdal/main.c
   grass/trunk/raster/r.out.gdal/r.out.gdal.html
Log:
attempt to solve ticket #73

Modified: grass/trunk/raster/r.out.gdal/export_band.c
===================================================================
--- grass/trunk/raster/r.out.gdal/export_band.c	2009-04-16 10:35:34 UTC (rev 36749)
+++ grass/trunk/raster/r.out.gdal/export_band.c	2009-04-16 11:18:13 UTC (rev 36750)
@@ -25,7 +25,8 @@
 int export_band(GDALDatasetH hMEMDS, int band, const char *name,
 		const char *mapset, struct Cell_head *cellhead,
 		RASTER_MAP_TYPE maptype, double nodataval,
-		const char *nodatakey, int suppress_main_colortable)
+		const char *nodatakey, int suppress_main_colortable,
+		int default_nodataval)
 {
 
     struct Colors sGrassColors;
@@ -63,14 +64,12 @@
 	G_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax);
     }
 
-    /* TODO: if data range exceeds export TYPE range exit with an error.
-       Otherwise the module doesn't know what to write for those values */
-
     /* suppress useless warnings */
     CPLPushErrorHandler(CPLQuietErrorHandler);
     GDALSetRasterColorInterpretation(hBand, GPI_RGB);
     CPLPopErrorHandler();
 
+    /* use default color rules if no color rules are given */
     if (G_read_colors(name, mapset, &sGrassColors) >= 0) {
 	int maxcolor, i;
 	CELL min, max;
@@ -165,13 +164,6 @@
 	if (!suppress_main_colortable)
 	    GDALSetRasterColorTable(hBand, hCT);
     }
-    else {
-	if (!suppress_main_colortable) {
-	    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);
@@ -189,11 +181,11 @@
 
     /* Copy data form GRASS raster to memory raster */
     int row, col;
-    int n_nulls = 0;
+    int n_nulls = 0, nodatavalmatch = 0;
 
     if (maptype == FCELL_TYPE) {
 
-	/* Source datatype understandible by GDAL */
+	/* Source datatype understandable by GDAL */
 	GDALDataType datatype = GDT_Float32;
 	FCELL fnullval = (FCELL) nodataval;
 
@@ -213,6 +205,9 @@
 		    }
 		    n_nulls++;
 		}
+		else if (((FCELL *) bufer)[col] == fnullval) {
+		    nodatavalmatch = 1;
+		}
 
 	    if (GDALRasterIO
 		(hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype,
@@ -244,6 +239,9 @@
 		    }
 		    n_nulls++;
 		}
+		else if (((DCELL *) bufer)[col] == dnullval) {
+		    nodatavalmatch = 1;
+		}
 
 	    if (GDALRasterIO
 		(hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype,
@@ -275,6 +273,9 @@
 		    }
 		    n_nulls++;
 		}
+		else if (((CELL *) bufer)[col] == inullval) {
+		    nodatavalmatch = 1;
+		}
 
 	    if (GDALRasterIO
 		(hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype,
@@ -286,16 +287,31 @@
 	}
     }
 
-    if (n_nulls > 0) {		/* TODO: && nodata_param NOT specified */
+    if (nodatavalmatch && n_nulls) {
+	if (default_nodataval) {  /* default nodataval didn't work */
+	    G_fatal_error(_("Raster band <%s> contains NULL cells and "
+	    "the default nodata value would lead to data loss. Please "
+	    "specify a nodata value with the %s parameter."),
+	     name, nodatakey);
+	}
+	else {  /* user-specified nodataval didn't work */
+	    G_fatal_error(_("Raster band <%s> contains NULL cells and "
+	    "the given nodata value would lead to data loss. Please "
+	    "specify a different nodata value with the %s parameter."),
+	     name, nodatakey);
+	}
+    }
+
+    if (n_nulls > 0 && default_nodataval) {
 	if (maptype == CELL_TYPE)
 	    G_important_message(_("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."),
+		       "You can specify a nodata value with the %s option."),
 		      (int)nodataval, nodatakey);
 	else
 	    G_important_message(_("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."),
+		       "You can specify a nodata value with the %s option."),
 		      nodataval, nodatakey);
     }
 

Modified: grass/trunk/raster/r.out.gdal/local_proto.h
===================================================================
--- grass/trunk/raster/r.out.gdal/local_proto.h	2009-04-16 10:35:34 UTC (rev 36749)
+++ grass/trunk/raster/r.out.gdal/local_proto.h	2009-04-16 11:18:13 UTC (rev 36750)
@@ -1,10 +1,8 @@
 #ifndef __LOCAL_PROTO_H__
 #define __LOCAL_PROTO_H__
 
+#include "gdal.h"
 
-#define GRASS_MAX_COLORS 100000	/* what is the right value? UInt16 -> 65535 ? */
-/* TODO: better- set from lesser of above and TYPE limits listed below */
-
 /* range limits */
 /*
   GDAL data type               minimum          maximum
@@ -18,38 +16,50 @@
   Float64, CFloat64          -1.79E308         1.79E308
 */
 
-/* TODO: for data export range checks and nodata value check
+/* copied from limits.h, checked against gdal-1.6.0/gcore/gdalrasterband.cpp */
 #define TYPE_BYTE_MIN		0
 #define TYPE_BYTE_MAX		255
-#define TYPE_INT16_MIN		-32768
+#define TYPE_INT16_MIN		(-32768)
 #define TYPE_INT16_MAX		32767
 #define TYPE_UINT16_MIN		0
 #define TYPE_UINT16_MAX		65535
 #define TYPE_UINT32_MIN		0
-#define TYPE_UINT32_MAX		4294967295     // better to use (double)(unsigned int)0xFFFFFFFFu  ?
-#define TYPE_INT32_MIN		-2147483648
+#define TYPE_UINT32_MAX		4294967295U
+#define TYPE_INT32_MIN		(-TYPE_INT32_MAX - 1)
 #define TYPE_INT32_MAX		2147483647
+
+/* new systems: FLT_MAX, DBL_MAX, old systems: MAXFLOAT, MAXDOUBLE, fallback: 3.4E38 and 1.79E308f */
+#ifdef FLT_MAX
+#define TYPE_FLOAT32_MIN	(-FLT_MAX)
+#define TYPE_FLOAT32_MAX	FLT_MAX
+#elif defined(MAX_FLOAT)
+#define TYPE_FLOAT32_MIN	(-MAXFLOAT)
+#define TYPE_FLOAT32_MAX	MAXFLOAT
+#else
 #define TYPE_FLOAT32_MIN	-3.4E38f
 #define TYPE_FLOAT32_MAX	3.4E38f
+#endif
+
+#ifdef DBL_MAX
+#define TYPE_FLOAT64_MIN	(-DBL_MAX)
+#define TYPE_FLOAT64_MAX	DBL_MAX
+#elif defined(MAXDOUBLE)
+#define TYPE_FLOAT64_MIN	(-MAXDOUBLE)
+#define TYPE_FLOAT64_MAX	MAXDOUBLE
+#else
 #define TYPE_FLOAT64_MIN	-1.79E308f
 #define TYPE_FLOAT64_MAX	1.79E308f
+#endif
 
- better to not define Ctypes here, rather in the code use
-  if( type == F16 || type== CF16 ) 
-#define TYPE_CINT16_MIN		TYPE_INT16_MIN
-#define TYPE_CINT16_MAX		TYPE_INT16_MAX
-#define TYPE_CINT32_MIN		TYPE_INT32_MIN
-#define TYPE_CINT32_MAX		TYPE_INT32_MAX
-#define TYPE_CFLOAT32_MIN	TYPE_FLOAT32_MIN
-#define TYPE_CFLOAT32_MAX	TYPE_FLOAT32_MAX
-#define TYPE_CFLOAT64_MIN	TYPE_FLOAT64_MIN
-#define TYPE_CFLOAT64_MAX	TYPE_FLOAT64_MAX
-*/
+#define GRASS_MAX_COLORS TYPE_UINT16_MAX
 
+/* main.c */
+int range_check(double, double, GDALDataType, char *);
+int nullvalue_check(double, GDALDataType);
 
 /* export_band.c */
 int export_band(GDALDatasetH, int, const char *, const char *,
 		struct Cell_head *, RASTER_MAP_TYPE, double,
-		const char *, int);
+		const char *, int, int);
 
 #endif /* __LOCAL_PROTO_H__ */

Modified: grass/trunk/raster/r.out.gdal/main.c
===================================================================
--- grass/trunk/raster/r.out.gdal/main.c	2009-04-16 10:35:34 UTC (rev 36749)
+++ grass/trunk/raster/r.out.gdal/main.c	2009-04-16 11:18:13 UTC (rev 36750)
@@ -30,7 +30,6 @@
 #include <grass/dbmi.h>
 
 #include "cpl_string.h"
-#include "gdal.h"
 #include "local_proto.h"
 
 
@@ -132,7 +131,7 @@
 
     flag_c = G_define_flag();
     flag_c->key = 'c';
-    flag_c->label = _("Do not export long colortable");
+    flag_c->label = _("Do not write GDAL standard colortable");
     flag_c->description = _("Only applicable to Byte or UInt16 data types.");
 
     input = G_define_standard_option(G_OPT_R_INPUT);
@@ -274,69 +273,75 @@
     GDALDataType datatype = GDT_Unknown;
     double nodataval;
 
+    maptype = CELL_TYPE;
+
     if (type->answer) {
 	/* reduce number of strcmps ... */
 	if (type->answer[0] == 'B') {
 	    datatype = GDT_Byte;
 	    maptype = CELL_TYPE;
-	    nodataval = (double)(unsigned char)0xFFu;
+	    nodataval = TYPE_BYTE_MIN;
 	}
 	else if (type->answer[0] == 'I') {
 	    if (strcmp(type->answer, "Int16") == 0) {
 		datatype = GDT_Int16;
 		maptype = CELL_TYPE;
-		nodataval = (double)(short)0x8000;
+		nodataval = TYPE_INT16_MIN;
 	    }
 	    else if (strcmp(type->answer, "Int32") == 0) {
 		datatype = GDT_Int32;
 		maptype = CELL_TYPE;
-		nodataval = (double)(int)0x80000000;
+		nodataval = TYPE_INT32_MIN;
 	    }
 	}
 	else if (type->answer[0] == 'U') {
 	    if (strcmp(type->answer, "UInt16") == 0) {
 		datatype = GDT_UInt16;
 		maptype = CELL_TYPE;
-		nodataval = (double)(unsigned short)0xFFFFu;
+		nodataval = TYPE_UINT16_MIN;
 	    }
 	    else if (strcmp(type->answer, "UInt32") == 0) {
 		datatype = GDT_UInt32;
 		maptype = DCELL_TYPE;
-		nodataval = (double)(unsigned int)0xFFFFFFFFu;
+		nodataval = TYPE_UINT32_MIN;
 	    }
 	}
 	else if (type->answer[0] == 'F') {
 	    if (strcmp(type->answer, "Float32") == 0) {
 		datatype = GDT_Float32;
 		maptype = FCELL_TYPE;
-		nodataval = -1E37f;
+		/* nodataval = TYPE_FLOAT32_MIN; */
+		nodataval = 0.0/0.0;
 	    }
 	    else if (strcmp(type->answer, "Float64") == 0) {
 		datatype = GDT_Float64;
 		maptype = DCELL_TYPE;
-		nodataval = -1E37f;
+		/* nodataval = TYPE_FLOAT64_MIN; */
+		nodataval = 0.0/0.0;
 	    }
 	}
 	else if (type->answer[0] == 'C') {
 	    if (strcmp(type->answer, "CInt16") == 0) {
 		datatype = GDT_CInt16;
 		maptype = CELL_TYPE;
-		nodataval = (double)(short)0x8000;
+		nodataval = TYPE_INT16_MIN;
 	    }
 	    else if (strcmp(type->answer, "CInt32") == 0) {
 		datatype = GDT_CInt32;
 		maptype = CELL_TYPE;
-		nodataval = (double)(int)0x80000000;
+		nodataval = TYPE_INT32_MIN;
 	    }
 	    else if (strcmp(type->answer, "CFloat32") == 0) {
 		datatype = GDT_CFloat32;
 		maptype = FCELL_TYPE;
-		nodataval = -1E37f;
+		/* nodataval = TYPE_FLOAT32_MIN; */
+		nodataval = 0.0/0.0;
 	    }
 	    else if (strcmp(type->answer, "CFloat64") == 0) {
 		datatype = GDT_CFloat64;
 		maptype = DCELL_TYPE;
-		nodataval = -1E37f;
+		/* nodataval = TYPE_FLOAT64_MIN; */
+		nodataval = 0.0/0.0;
 	    }
 	}
     }
@@ -357,41 +362,44 @@
 	maptype = G_raster_map_type(ref.file[0].name, ref.file[0].mapset);
 	if (maptype == FCELL_TYPE) {
 	    datatype = GDT_Float32;
-	    nodataval = -1E37f;
+	    /* nodataval = TYPE_FLOAT32_MIN; */
+	    nodataval = 0.0/0.0;
 	}
 	else if (maptype == DCELL_TYPE) {
 	    datatype = GDT_Float64;
-	    nodataval = -1E37f;
+	    /* nodataval = TYPE_FLOAT64_MIN; */
+	    nodataval = 0.0/0.0;
 	}
 	else {
 	    /* Special tricks for GeoTIFF color table support and such */
 	    if (dfCellMin >= 0 && dfCellMax < 256) {
 		datatype = GDT_Byte;
-		nodataval = (double)(unsigned char)0xFFu;
+		nodataval = TYPE_BYTE_MIN;
 	    }
 	    else {
 		if (dfCellMin >= 0 && dfCellMax < 65536) {
 		    datatype = GDT_UInt16;
-		    nodataval = (double)(short)0x8000;
+		    nodataval = TYPE_UINT16_MIN;
 		}
 		else {
 		    datatype = GDT_Int32;	/* need to fine tune this more? */
-		    nodataval = (double)(int)0x80000000;
+		    nodataval = TYPE_INT32_MIN;
 		}
 	    }
 	}
     }
 
-    /* force nodata-value if needed */
+    /* default or user-specified nodata-value ? */
+    int default_nodataval = 1;
+
     if (nodataopt->answer) {
 	nodataval = atof(nodataopt->answer);
+	default_nodataval = 0;
+	/* check nodataval here, not in export_band(), because it is specified only once */
+	if (nullvalue_check(nodataval, datatype))
+	    G_fatal_error("Raster export aborted.");
     }
 
-    /* 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" :
@@ -469,10 +477,27 @@
 						     ref.file[band].mapset),
 			      band + 1);
 	}
+	/* do range check here because we don't have GDALDataType in export_band() */
+	if (G_read_fp_range
+	    (ref.file[band].name, ref.file[band].mapset, &sRange) == -1) {
+	    bHaveMinMax = FALSE;
+	}
+	else {
+	    bHaveMinMax = TRUE;
+	    G_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax);
+	}
+	G_debug(3, "Range: min: %f, max: %f", dfCellMin, dfCellMax);
+	if (bHaveMinMax == TRUE) {
+	    if (range_check
+		(dfCellMin, dfCellMax, datatype, ref.file[band].name))
+		G_fatal_error("Raster export aborted");
+	}
+
+	/* ready to export */
 	if (export_band
 	    (hCurrDS, band + 1, ref.file[band].name, ref.file[band].mapset,
-	     &cellhead, maptype, nodataval, nodataopt->key,
-	     flag_c->answer) < 0)
+	     &cellhead, maptype, nodataval, nodataopt->key, flag_c->answer,
+	     default_nodataval) < 0)
 	    G_warning(_("Unable to export raster map <%s>"),
 		      ref.file[band].name);
     }
@@ -497,3 +522,202 @@
     G_done_msg(" ");
     exit(EXIT_SUCCESS);
 }
+
+
+int range_check(double min, double max, GDALDataType datatype, char *name)
+{
+    /* what accuracy to use to print min max for FLOAT32 and FLOAT64? %g enough? */
+
+    switch (datatype) {
+    case GDT_Byte:
+	if (min < TYPE_BYTE_MIN || max > TYPE_BYTE_MAX) {
+	    G_warning(_("Selected GDAL datatype does not cover data range."));
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_BYTE_MIN,
+		      TYPE_BYTE_MAX);
+	    G_warning(_("Raster map <%s> range: %g - %g"), name, min, max);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_UInt16:
+	if (min < TYPE_UINT16_MIN || max > TYPE_UINT16_MAX) {
+	    G_warning(_("Selected GDAL datatype does not cover data range."));
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_UINT16_MIN,
+		      TYPE_UINT16_MAX);
+	    G_warning(_("Raster map <%s> range: %g - %g"), name, min, max);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Int16:
+    case GDT_CInt16:
+	if (min < TYPE_INT16_MIN || max > TYPE_INT16_MAX) {
+	    G_warning(_("Selected GDAL datatype does not cover data range."));
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_INT16_MIN,
+		      TYPE_INT16_MAX);
+	    G_warning(_("Raster map <%s> range: %g - %g"), name, min, max);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Int32:
+    case GDT_CInt32:
+	if (min < TYPE_INT32_MIN || max > TYPE_INT32_MAX) {
+	    G_warning(_("Selected GDAL datatype does not cover data range."));
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_INT32_MIN,
+		      TYPE_INT32_MAX);
+	    G_warning(_("Raster map <%s> range: %g - %g"), name, min, max);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_UInt32:
+	if (min < TYPE_UINT32_MIN || max > TYPE_UINT32_MAX) {
+	    G_warning(_("Selected GDAL datatype does not cover data range."));
+	    G_warning(_("GDAL datatype: %s, range: %u - %u"),
+		      GDALGetDataTypeName(datatype), TYPE_UINT32_MIN,
+		      TYPE_UINT32_MAX);
+	    G_warning(_("Raster map <%s> range: %g - %g"), name, min, max);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Float32:
+    case GDT_CFloat32:
+	if (min < TYPE_FLOAT32_MIN || max > TYPE_FLOAT32_MAX) {
+	    G_warning(_("Selected GDAL datatype does not cover data range."));
+	    G_warning(_("GDAL datatype: %s, range: %g - %g"),
+		      GDALGetDataTypeName(datatype), TYPE_FLOAT32_MIN,
+		      TYPE_FLOAT32_MAX);
+	    G_warning(_("Raster map <%s> range: %g - %g"), name, min, max);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Float64:
+    case GDT_CFloat64:
+	/* not possible because DCELL is FLOAT64, not 128bit floating point, but anyway... */
+	if (min < TYPE_FLOAT64_MIN || max > TYPE_FLOAT64_MAX) {
+	    G_warning(_("Selected GDAL datatype does not cover data range."));
+	    G_warning(_("GDAL datatype: %s, range: %g - %g"),
+		      GDALGetDataTypeName(datatype), TYPE_FLOAT64_MIN,
+		      TYPE_FLOAT64_MAX);
+	    G_warning(_("Raster map <%s> range: %g - %g"), name, min, max);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    default:
+	return 0;
+    }
+}
+
+int nullvalue_check(double nodataval, GDALDataType datatype)
+{
+    /* what accuracy to use to print nodataval for FLOAT32 and FLOAT64? %g enough? */
+
+    switch (datatype) {
+    case GDT_Byte:
+	if (nodataval < TYPE_BYTE_MIN || nodataval > TYPE_BYTE_MAX) {
+	    G_warning(_("Specified nodata value %d is not covered by range of selected GDAL datatype."),
+		      (int) nodataval);
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_BYTE_MIN,
+		      TYPE_BYTE_MAX);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_UInt16:
+	if (nodataval < TYPE_UINT16_MIN || nodataval > TYPE_UINT16_MAX) {
+	    G_warning(_("Specified nodata value %d is not covered by range of selected GDAL datatype."),
+		      (int) nodataval);
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_UINT16_MIN,
+		      TYPE_UINT16_MAX);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Int16:
+    case GDT_CInt16:
+	if (nodataval < TYPE_INT16_MIN || nodataval > TYPE_INT16_MAX) {
+	    G_warning(_("Specified nodata value %d is not covered by range of selected GDAL datatype."),
+		      (int) nodataval);
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_INT16_MIN,
+		      TYPE_INT16_MAX);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Int32:
+    case GDT_CInt32:
+	if (nodataval < TYPE_INT32_MIN || nodataval > TYPE_INT32_MAX) {
+	    G_warning(_("Specified nodata value %lld is not covered by range of selected GDAL datatype."),
+		      (long long) nodataval);
+	    G_warning(_("GDAL datatype: %s, range: %d - %d"),
+		      GDALGetDataTypeName(datatype), TYPE_INT32_MIN,
+		      TYPE_INT32_MAX);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_UInt32:
+	if (nodataval < TYPE_UINT32_MIN || nodataval > TYPE_UINT32_MAX) {
+	    G_warning(_("Specified nodata value %lld is not covered by range of selected GDAL datatype."),
+		      (long long) nodataval);
+	    G_warning(_("GDAL datatype: %s, range: %u - %u"),
+		      GDALGetDataTypeName(datatype), TYPE_UINT32_MIN,
+		      TYPE_UINT32_MAX);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Float32:
+    case GDT_CFloat32:
+	if (nodataval < TYPE_FLOAT32_MIN || nodataval > TYPE_FLOAT32_MAX) {
+	    G_warning(_("Specified nodata value %g is not covered by range of selected GDAL datatype."),
+		      nodataval);
+	    G_warning(_("GDAL datatype: %s, range: %g - %g"),
+		      GDALGetDataTypeName(datatype), TYPE_FLOAT32_MIN,
+		      TYPE_FLOAT32_MAX);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    case GDT_Float64:
+    case GDT_CFloat64:
+	/* not possible because double is FLOAT64, not 128bit floating point */
+	if (nodataval < TYPE_FLOAT64_MIN || nodataval > TYPE_FLOAT64_MAX) {
+	    G_warning(_("Specified nodata value %g is not covered by range of selected GDAL datatype."),
+		      nodataval);
+	    G_warning(_("GDAL datatype: %s, range: %g - %g"),
+		      GDALGetDataTypeName(datatype), TYPE_FLOAT64_MIN,
+		      TYPE_FLOAT64_MAX);
+	    return 1;
+	}
+	else
+	    return 0;
+
+    default:
+	return 0;
+    }
+}

Modified: grass/trunk/raster/r.out.gdal/r.out.gdal.html
===================================================================
--- grass/trunk/raster/r.out.gdal/r.out.gdal.html	2009-04-16 10:35:34 UTC (rev 36749)
+++ grass/trunk/raster/r.out.gdal/r.out.gdal.html	2009-04-16 11:18:13 UTC (rev 36750)
@@ -1,11 +1,18 @@
 <h2>DESCRIPTION</h2>
 
 <em>r.out.gdal</em> allows a user to export a GRASS raster map layer
-into any GDAL supported raster map format.
-
-For possible <em>metaopt</em> parameters see the individual
-<a href="http://www.gdal.org/formats_list.html">supported formats</a> pages
-on the GDAL website.
+into any GDAL supported raster map format. If a GRASS raster map is
+exported for a particular application, the application's native format
+would be preferrable. GeoTIFF is supported by a wide range of
+applications (see also <b>NOTES</b> on GeoTIFF below).
+<p>
+To specify multiple creation options use a comma separated list
+(<em>createopt="TFW=YES,COMPRESS=DEFLATE"</em>).
+<p>
+For possible <em>createopt</em> and <em>metaopt</em> parameters please
+consult the individual
+<a href="http://www.gdal.org/formats_list.html">supported formats</a>
+pages on the GDAL website.
 The <em>createopt</em> parameter may be used to create TFW or World files
 ("TFW=YES","WORLDFILE=ON").
 <p>
@@ -56,19 +63,7 @@
 
 <h2>NOTES</h2>
 
-When writing out multi-band GeoTIFF images for users of ESRI software or
-ImageMagick, the interleaving mode should be set to "pixel" using
-<em>createopt="INTERLEAVE=PIXEL"</em>. BAND interleaving is slightly more
-efficient, but not supported by some applications.
-<!-- GDAL switched default from BAND to PIXEL interleave on 08/01/07 (r11823) -->
-This issue only arises when writing out multi-band imagery groups.
-Some software may not recognize all of the compression methods available.
-<!-- e.g. data destined for ESRI software should use COMPRESS=LZW/PACKBITS/DEFLATE ??? -->
-
 <p>
-To specify multiple options use a comma separated list
-(<em>createopt="TFW=YES,COMPRESS=DEFLATE"</em>).
-<p>
 Out of the GDAL data types, the closest match for GRASS CELL, FCELL and
 DCELL rasters are respectively Int32, Float32 and Float64. These are not
 exact equivalents, but they will preserve the maximum possible data range
@@ -80,8 +75,8 @@
 check the data type and range for your GRASS raster, refer to specific
 format documentation (on the <a href="http://www.gdal.org/">GDAL website</a>),
 format vendor's documentation, and e.g. the Wikipedia article
-<em><a href="http://en.wikipedia.org/wiki/C_syntax#Typical_boundaries_of_primitive_integral_types">Typical
-  boundaries of primitive integral types</a></em>
+<em><a href="http://en.wikipedia.org/wiki/C_syntax#Typical_boundaries_of_primitive_integral_types">
+Typical boundaries of primitive integral types</a></em>
 for details.
 
 
@@ -104,16 +99,45 @@
 use Byte rather than UInt16; use Int16 rather than Int32; or use Float32
 rather than Float64. In addition, the COMPRESS <b>createopt</b> used can
 have a very large impact on the size of the output file.
+<p>
+Some software may not recognize all of the compression methods
+available for a given file format, and certain compression methods may
+only be supported for certain data types (depends on vendor and version).
+<!-- e.g. data destined for ESRI software should use COMPRESS=LZW/PACKBITS/DEFLATE ??? -->
+<p>
+<em>r.out.gdal</em> exports may appear all black or gray on initial
+display in other GIS software. This is not a bug of <em>r.out.gdal</em>,
+but often caused by the default color table assigned by that software.
+The dafault color table may be grayscale covering the whole range of
+possible values which is very large for e.g. Int32 or Float32. E.g.
+stretching the color table to actual min/max would help (sometimes under
+symbology).
 
+<h4>GeoTIFF caveats</h4>
 
+GeoTIFF exports can only be displayed by standard image viewers
+if the GDAL data type was set to Byte and the GeoTIFF contains either
+one or three bands. All other data types and numbers of bands can be
+properly read with GIS software only. Although GeoTIFF files usually
+have a .tif extension, these files are not necessarily images but
+first of all spatial raster datasets, e.g. SRTM DEM version 4.
+<p>
+When writing out multi-band GeoTIFF images for users of ESRI software or
+ImageMagick, the interleaving mode should be set to "pixel" using
+<em>createopt="INTERLEAVE=PIXEL"</em>. BAND interleaving is slightly more
+efficient, but not supported by some applications.
+<!-- GDAL switched default from BAND to PIXEL interleave on 08/01/07 (r11823) -->
+This issue only arises when writing out multi-band imagery groups.
+<p>
+
 <h4>Improving GeoTIFF compatibility</h4>
 
-To create a highly compatibility GeoTIFF with various other GIS software 
-packages, it is recommended to keep the GeoTIFF file as simple as possible.
-You will have to experiment with which options your software is compatible
-with, as this varies widely between vendors and versions. Long term, the
-less metadata you have to remove the more self-documenting (and useful)
-the dataset will be.
+To create a GeoTIFF that is highly compatibility with various other GIS
+software packages, it is recommended to keep the GeoTIFF file as simple
+as possible. You will have to experiment with which options your
+software is compatible with, as this varies widely between vendors and
+versions. Long term, the less metadata you have to remove the more
+self-documenting (and useful) the dataset will be.
 <p>
 Here are some things to try:
 
@@ -127,8 +151,10 @@
 compressed with software like <tt>zip</tt>, <tt>gnuzip</tt>, or <tt>bzip2</tt>.
 
 <li>Skip exporting the color table. Color tables are not always properly
-rendered and the GeoTIFF file can appear completely black. If you are lucky
-the problematic software package has a method to reset the color table.
+rendered, particularly for type UInt16, and the GeoTIFF file can appear
+completely black. If you are lucky the problematic software package has
+a method to reset the color table and assign a new color table
+(sometimes called symbology).
 
 <li>Keep metadata simple with <tt>createopt="PROFILE=GeoTIFF"</tt> or 
 <tt>createopt="PROFILE=BASELINE"</tt>. With BASELINE no GDAL or GeoTIFF
@@ -150,14 +176,14 @@
 
 <h4>Export a DCELL raster map in GeoTIFF format suitable for ESRI software:</h4>
 <div class="code"><pre>
-r.out.gdal in=elevation.10m out=ned_elev10m.tif type=Float64 createopt="TFW=YES"
+r.out.gdal in=elevation.10m out=ned_elev10m.tif type=Float64 createopt="PROFILE=GeoTIFF,TFW=YES"
 </pre></div>
 <p>
 
 <h4>Export R,G,B imagery bands in GeoTIFF format suitable for ESRI software:</h4>
 <div class="code"><pre>
 i.group group=nc_landsat_rgb input=lsat7_2002_30,lsat7_2002_20,lsat7_2002_10
-r.out.gdal in=nc_landsat_rgb out=nc_landsat_rgb.tif type=Byte createopt="INTERLEAVE=PIXEL,TFW=YES"
+r.out.gdal in=nc_landsat_rgb out=nc_landsat_rgb.tif type=Byte createopt="PROFILE=GeoTIFF,INTERLEAVE=PIXEL,TFW=YES"
 </pre></div>
 <p>
 



More information about the grass-commit mailing list