[GRASS-SVN] r34748 - in grass/trunk: include lib/gis raster raster/r.external.out

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Dec 6 04:05:27 EST 2008


Author: glynn
Date: 2008-12-06 04:05:27 -0500 (Sat, 06 Dec 2008)
New Revision: 34748

Added:
   grass/trunk/raster/r.external.out/
   grass/trunk/raster/r.external.out/Makefile
   grass/trunk/raster/r.external.out/main.c
   grass/trunk/raster/r.external.out/r.external.out.html
Modified:
   grass/trunk/include/gisdefs.h
   grass/trunk/lib/gis/closecell.c
   grass/trunk/lib/gis/gdal.c
   grass/trunk/lib/gis/opencell.c
   grass/trunk/lib/gis/put_row.c
   grass/trunk/raster/Makefile
Log:
Add write support to GDAL-link, r.external.out


Modified: grass/trunk/include/gisdefs.h
===================================================================
--- grass/trunk/include/gisdefs.h	2008-12-06 09:04:16 UTC (rev 34747)
+++ grass/trunk/include/gisdefs.h	2008-12-06 09:05:27 UTC (rev 34748)
@@ -549,7 +549,9 @@
 /* gdal.c */
 void G_init_gdal(void);
 struct GDAL_link *G_get_gdal_link(const char *, const char *);
+struct GDAL_link *G_create_gdal_link(const char *, RASTER_MAP_TYPE);
 void G_close_gdal_link(struct GDAL_link *);
+int G_close_gdal_write_link(struct GDAL_link *);
 
 /* geodesic.c */
 int G_begin_geodesic_equation(double, double, double, double);
@@ -932,7 +934,6 @@
 
 /* put_row.c */
 int G_put_map_row(int, const CELL *);
-int G__put_null_value_row(int, const char *);
 int G_put_raster_row(int, const void *, RASTER_MAP_TYPE);
 int G_put_c_raster_row(int, const CELL *);
 int G_put_f_raster_row(int, const FCELL *);

Modified: grass/trunk/lib/gis/closecell.c
===================================================================
--- grass/trunk/lib/gis/closecell.c	2008-12-06 09:04:16 UTC (rev 34747)
+++ grass/trunk/lib/gis/closecell.c	2008-12-06 09:05:27 UTC (rev 34748)
@@ -158,17 +158,178 @@
     return 1;
 }
 
-static int close_new(int fd, int ok)
+static void write_support_files(int fd)
 {
     struct fileinfo *fcb = &G__.fileinfo[fd];
-    int stat;
     struct Categories cats;
     struct History hist;
+    CELL cell_min, cell_max;
     char path[GPATH_MAX];
-    CELL cell_min, cell_max;
-    int row, i, open_mode;
+
+    /* remove color table */
+    G_remove_colors(fcb->name, "");
+
+    /* create a history file */
+    G_short_history(fcb->name, "raster", &hist);
+    G_write_history(fcb->name, &hist);
+
+    /* write the range */
+    if (fcb->map_type == CELL_TYPE) {
+	G_write_range(fcb->name, &fcb->range);
+	G__remove_fp_range(fcb->name);
+    }
+    /*NOTE: int range for floating point maps is not written out */
+    else {			/* if(fcb->map_type != CELL_TYPE) */
+
+	G_write_fp_range(fcb->name, &fcb->fp_range);
+	G_construct_default_range(&fcb->range);
+	/* this range will be used to add default rule to quant structure */
+    }
+
+    if (fcb->map_type != CELL_TYPE)
+	fcb->cellhd.format = -1;
+    else			/* CELL map */
+	fcb->cellhd.format = fcb->nbytes - 1;
+
+    /* write header file */
+    G_put_cellhd(fcb->name, &fcb->cellhd);
+
+    /* if map is floating point write the quant rules, otherwise remove f_quant */
+    if (fcb->map_type != CELL_TYPE) {
+	/* DEFAULT RANGE QUANT
+	   G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max);
+	   if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max))
+	   {
+	   G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
+	   G_quant_add_rule(&fcb->quant, dcell_min, dcell_max, 
+	   cell_min, cell_max);
+	   }
+	*/
+	G_quant_round(&fcb->quant);
+	if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0)
+	    G_warning(_("unable to write quant file!"));
+    }
+    else {
+	/* remove cell_misc/name/f_quant */
+	G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name,
+			  fcb->mapset);
+	remove(path);
+    }
+
+    /* create empty cats file */
+    G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
+    if (G_is_c_null_value(&cell_max))
+	cell_max = 0;
+    G_init_cats(cell_max, (char *)NULL, &cats);
+    G_write_cats(fcb->name, &cats);
+    G_free_cats(&cats);
+
+    /* write the histogram */
+    /* only works for integer maps */
+    if ((fcb->map_type == CELL_TYPE)
+	&& (fcb->want_histogram)) {
+	G_write_histogram_cs(fcb->name, &fcb->statf);
+	G_free_cell_stats(&fcb->statf);
+    }
+    else {
+	G_remove_histogram(fcb->name);
+    }
+}
+
+static int close_new_gdal(int fd, int ok)
+{
+    struct fileinfo *fcb = &G__.fileinfo[fd];
+    char path[GPATH_MAX];
+    int stat = 1;
+
+    if (ok) {
+	int cell_fd;
+
+	G_debug(1, "close %s GDAL", fcb->name);
+
+	if (fcb->cur_row < fcb->cellhd.rows) {
+	    int row;
+
+	    G_zero_raster_buf(fcb->data, fcb->map_type);
+	    for (row = fcb->cur_row; row < fcb->cellhd.rows; row++)
+		G_put_raster_row(fd, fcb->data, fcb->map_type);
+	    G_free(fcb->data);
+	    fcb->data = NULL;
+	}
+
+	/* create path : full null file name */
+	G__make_mapset_element_misc("cell_misc", fcb->name);
+	G__file_name_misc(path, "cell_misc", NULL_FILE, fcb->name,
+			  G_mapset());
+	remove(path);
+
+	/* write 0-length cell file */
+	G__make_mapset_element("cell");
+	G__file_name(path, "cell", fcb->name, fcb->mapset);
+	cell_fd = creat(path, 0666);
+	close(cell_fd);
+
+	if (fcb->map_type != CELL_TYPE) {	/* floating point map */
+	    if (write_fp_format(fd) != 0) {
+		G_warning(_("Error writing floating point format file for map %s"),
+			  fcb->name);
+		stat = -1;
+	    }
+
+	    /* write 0-length fcell file */
+	    G__make_mapset_element("fcell");
+	    G__file_name(path, "fcell", fcb->name, fcb->mapset);
+	    cell_fd = creat(path, 0666);
+	    close(cell_fd);
+	}
+	else {
+	    /* remove fcell/name file */
+	    G__file_name(path, "fcell", fcb->name, fcb->mapset);
+	    remove(path);
+	    /* remove cell_misc/name/f_format */
+	    G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name,
+			      fcb->mapset);
+	    remove(path);
+	}
+
+	if (G_close_gdal_write_link(fcb->gdal) < 0)
+	    stat = -1;
+    }
+    else {
+	remove(fcb->gdal->filename);
+	G_close_gdal_link(fcb->gdal);
+    }
+
+    /* NOW CLOSE THE FILE DESCRIPTOR */
+    close(fd);
+    fcb->open_mode = -1;
+
+    if (fcb->data != NULL)
+	G_free(fcb->data);
+
+    if (ok)
+	write_support_files(fd);
+
+    G_free(fcb->name);
+    G_free(fcb->mapset);
+
+    if (fcb->map_type != CELL_TYPE)
+	G_quant_free(&fcb->quant);
+
+    return stat;
+}
+
+static int close_new(int fd, int ok)
+{
+    struct fileinfo *fcb = &G__.fileinfo[fd];
+    int stat;
+    char path[GPATH_MAX];
+    int row, i;
     const char *CELL_DIR;
 
+    if (fcb->gdal)
+	return close_new_gdal(fd, ok);
+
     if (ok) {
 	switch (fcb->open_mode) {
 	case OPEN_NEW_COMPRESSED:
@@ -272,8 +433,6 @@
     /* NOW CLOSE THE FILE DESCRIPTOR */
 
     close(fd);
-    /* remember open_mode */
-    open_mode = fcb->open_mode;
     fcb->open_mode = -1;
 
     if (fcb->data != NULL)
@@ -307,77 +466,9 @@
 	G_free(fcb->temp_name);
     }
 
-    if (ok) {
-	/* remove color table */
-	G_remove_colors(fcb->name, "");
+    if (ok)
+	write_support_files(fd);
 
-	/* create a history file */
-	G_short_history(fcb->name, "raster", &hist);
-	G_write_history(fcb->name, &hist);
-
-	/* write the range */
-	if (fcb->map_type == CELL_TYPE) {
-	    G_write_range(fcb->name, &fcb->range);
-	    G__remove_fp_range(fcb->name);
-	}
-	/*NOTE: int range for floating point maps is not written out */
-	else {			/* if(fcb->map_type != CELL_TYPE) */
-
-	    G_write_fp_range(fcb->name, &fcb->fp_range);
-	    G_construct_default_range(&fcb->range);
-	    /* this range will be used to add default rule to quant structure */
-	}
-
-	if (fcb->map_type != CELL_TYPE)
-	    fcb->cellhd.format = -1;
-	else			/* CELL map */
-	    fcb->cellhd.format = fcb->nbytes - 1;
-
-	/* write header file */
-	G_put_cellhd(fcb->name, &fcb->cellhd);
-
-	/* if map is floating point write the quant rules, otherwise remove f_quant */
-	if (fcb->map_type != CELL_TYPE) {
-	    /* DEFAULT RANGE QUANT
-	       G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max);
-	       if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max))
-	       {
-	       G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
-	       G_quant_add_rule(&fcb->quant, dcell_min, dcell_max, 
-	       cell_min, cell_max);
-	       }
-	     */
-	    G_quant_round(&fcb->quant);
-	    if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0)
-		G_warning(_("unable to write quant file!"));
-	}
-	else {
-	    /* remove cell_misc/name/f_quant */
-	    G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name,
-			      fcb->mapset);
-	    remove(path);
-	}
-
-	/* create empty cats file */
-	G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
-	if (G_is_c_null_value(&cell_max))
-	    cell_max = 0;
-	G_init_cats(cell_max, (char *)NULL, &cats);
-	G_write_cats(fcb->name, &cats);
-	G_free_cats(&cats);
-
-	/* write the histogram */
-	/* only works for integer maps */
-	if ((fcb->map_type == CELL_TYPE)
-	    && (fcb->want_histogram)) {
-	    G_write_histogram_cs(fcb->name, &fcb->statf);
-	    G_free_cell_stats(&fcb->statf);
-	}
-	else {
-	    G_remove_histogram(fcb->name);
-	}
-    }				/* OK */
-
     G_free(fcb->name);
     G_free(fcb->mapset);
 

Modified: grass/trunk/lib/gis/gdal.c
===================================================================
--- grass/trunk/lib/gis/gdal.c	2008-12-06 09:04:16 UTC (rev 34747)
+++ grass/trunk/lib/gis/gdal.c	2008-12-06 09:05:27 UTC (rev 34748)
@@ -1,6 +1,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <grass/config.h>
 #include <grass/gis.h>
 #include <grass/glocale.h>
@@ -31,6 +32,15 @@
     int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
     void * pBuffer, int nBXSize, int nBYSize,GDALDataType eBDataType,
     int nPixelSpace, int nLineSpace);
+static GDALDriverH CPL_STDCALL (*pGDALGetDriverByName)(const char *);
+static const char * CPL_STDCALL (*pGDALGetMetadataItem)(GDALMajorObjectH, const char *, const char *);
+static GDALDatasetH CPL_STDCALL (*pGDALCreate)(GDALDriverH hDriver, const char *, int, int, int, GDALDataType, char **);
+static GDALDatasetH CPL_STDCALL (*pGDALCreateCopy)(GDALDriverH, const char *, GDALDatasetH, int, char **, GDALProgressFunc, void *);
+static CPLErr CPL_STDCALL (*pGDALSetRasterNoDataValue)(GDALRasterBandH, double);
+static CPLErr CPL_STDCALL (*pGDALSetGeoTransform)(GDALDatasetH, double *);
+static CPLErr CPL_STDCALL (*pGDALSetProjection)(GDALDatasetH, const char *);
+static const char * CPL_STDCALL (*pGDALGetDriverShortName)(GDALDriverH);
+static GDALDriverH CPL_STDCALL (*pGDALGetDatasetDriver)(GDALDatasetH);
 
 #if GDAL_DYNAMIC
 # if defined(__unix) && !defined(__unix__)
@@ -98,22 +108,40 @@
 {
     load_library();
 
-    pGDALAllRegister   = get_symbol("GDALAllRegister");
-    pGDALOpen          = get_symbol("GDALOpen");
-    pGDALClose         = get_symbol("GDALClose");
-    pGDALGetRasterBand = get_symbol("GDALGetRasterBand");
-    pGDALRasterIO      = get_symbol("GDALRasterIO");
+    pGDALAllRegister          = get_symbol("GDALAllRegister");
+    pGDALOpen                 = get_symbol("GDALOpen");
+    pGDALClose                = get_symbol("GDALClose");
+    pGDALGetRasterBand        = get_symbol("GDALGetRasterBand");
+    pGDALRasterIO             = get_symbol("GDALRasterIO");
+    pGDALGetDriverByName      = get_symbol("GDALGetDriverByName");
+    pGDALGetMetadataItem      = get_symbol("GDALGetMetadataItem");
+    pGDALCreate               = get_symbol("GDALCreate");
+    pGDALCreateCopy           = get_symbol("GDALCreateCopy");
+    pGDALSetRasterNoDataValue = get_symbol("GDALSetRasterNoDataValue");
+    pGDALSetGeoTransform      = get_symbol("GDALSetGeoTransform");
+    pGDALSetProjection        = get_symbol("GDALSetProjection");
+    pGDALGetDriverShortName   = get_symbol("GDALGetDriverShortName");
+    pGDALGetDatasetDriver     = get_symbol("GDALGetDatasetDriver");
 }
 
 #else /* GDAL_DYNAMIC */
 
 static void init_gdal(void)
 {
-    pGDALAllRegister   = &GDALAllRegister;
-    pGDALOpen          = &GDALOpen;
-    pGDALClose         = &GDALClose;
-    pGDALGetRasterBand = &GDALGetRasterBand;
-    pGDALRasterIO      = &GDALRasterIO;
+    pGDALAllRegister          = &GDALAllRegister;
+    pGDALOpen                 = &GDALOpen;
+    pGDALClose                = &GDALClose;
+    pGDALGetRasterBand        = &GDALGetRasterBand;
+    pGDALRasterIO             = &GDALRasterIO;
+    pGDALGetDriverByName      = &GDALGetDriverByName;
+    pGDALGetMetadataItem      = &GDALGetMetadataItem;
+    pGDALCreate               = &GDALCreate;
+    pGDALCreateCopy           = &GDALCreateCopy;
+    pGDALSetRasterNoDataValue = &GDALSetRasterNoDataValue;
+    pGDALSetGeoTransform      = &GDALSetGeoTransform;
+    pGDALSetProjection        = &GDALSetProjection;
+    pGDALGetDriverShortName   = &GDALGetDriverShortName;
+    pGDALGetDatasetDriver     = &GDALGetDatasetDriver;
 }
 
 #endif /* GDAL_DYNAMIC */
@@ -246,6 +274,211 @@
     return gdal;
 }
 
+struct GDAL_Options {
+    const char *dir;
+    const char *ext;
+    const char *format;
+    char **options;
+};
+
+static struct state {
+    int initialized;
+    struct GDAL_Options opts;
+    struct Key_Value *projinfo, *projunits;
+    char *srswkt;
+} state;
+
+static struct state *st = &state;
+
+static void read_gdal_options(void)
+{
+    FILE *fp;
+    struct Key_Value *key_val;
+    const char *p;
+
+    fp = G_fopen_old("", "GDAL", G_mapset());
+    if (!fp)
+	G_fatal_error(_("Unable to open GDAL file"));
+    key_val = G_fread_key_value(fp);
+    fclose(fp);
+
+    p = G_find_key_value("directory", key_val);
+    if (!p)
+	p = "gdal";
+    if (*p == '/')
+	st->opts.dir = G_store(p);
+    else;
+    {
+	char path[GPATH_MAX];
+	G__file_name(path, p, "", G_mapset());
+	st->opts.dir = G_store(path);
+	if (access(path, 0) != 0)
+	    G__make_mapset_element(p);
+    }
+
+    p = G_find_key_value("extension", key_val);
+    st->opts.ext = G_store(p ? p : "");
+
+    p = G_find_key_value("format", key_val);
+    st->opts.format = G_store(p ? p : "GTiff");
+
+    p = G_find_key_value("options", key_val);
+    st->opts.options = p ? G_tokenize(p, ",") : NULL;
+
+    G_free_key_value(key_val);
+}
+
+struct GDAL_link *G_create_gdal_link(const char *name, RASTER_MAP_TYPE map_type)
+{
+#ifdef GDAL_LINK
+    char path[GPATH_MAX];
+    GDALDriverH driver;
+    double transform[6];
+    struct GDAL_link *gdal;
+    FILE *fp;
+    struct Key_Value *key_val;
+    char buf[32];
+
+
+    G_init_gdal();
+
+    if (!G_is_initialized(&st->initialized)) {
+	read_gdal_options();
+	st->projinfo = G_get_projinfo();
+	st->projunits = G_get_projunits();
+#if 0
+	/* We cannot use GPJ_grass_to_wkt() here because that would create a
+	   circular dependency between libgis and libgproj */
+	if (st->projinfo && st->projunits)
+	    st->srswkt = GPJ_grass_to_wkt(st->projinfo, st->projunits);
+#endif
+	G_initialize_done(&st->initialized);
+    }
+
+    gdal = G_calloc(1, sizeof(struct GDAL_link));
+
+    sprintf(path, "%s/%s%s", st->opts.dir, name, st->opts.ext);
+    gdal->filename = G_store(path);
+    gdal->band_num = 1;
+    gdal->hflip = 0;
+    gdal->vflip = 0;
+
+    switch (map_type) {
+    case CELL_TYPE:
+	switch (G__.nbytes) {
+	case 1:
+	    gdal->type = GDT_Byte;
+	    gdal->null_val = (DCELL) 0xFF;
+	    break;
+	case 2:
+	    gdal->type = GDT_UInt16;
+	    gdal->null_val = (DCELL) 0xFFFF;
+	    break;
+	case 3:
+	case 4:
+	    gdal->type = GDT_Int32;
+	    gdal->null_val = (DCELL) 0x80000000U;
+	    break;
+	}
+	break;
+    case FCELL_TYPE:
+	gdal->type = GDT_Float32;
+	G_set_d_null_value(&gdal->null_val, 1);
+	break;
+    case DCELL_TYPE:
+	gdal->type = GDT_Float64;
+	G_set_d_null_value(&gdal->null_val, 1);
+	break;
+    default:
+	G_fatal_error(_("Invalid map type <%d>"), map_type);
+	break;
+    }
+
+    driver = (*pGDALGetDriverByName)(st->opts.format);
+    if (!driver)
+	G_fatal_error(_("Unable to get <%s> driver"), st->opts.format);
+
+    /* Does driver support GDALCreate ? */
+    if ((*pGDALGetMetadataItem)(driver, GDAL_DCAP_CREATE, NULL))
+    {
+	gdal->data = (*pGDALCreate)(driver, gdal->filename, G__.window.cols, G__.window.rows,
+				1, gdal->type, st->opts.options);
+	if (!gdal->data)
+	    G_fatal_error(_("Unable to create <%s> dataset using <%s> driver"),
+			  name, st->opts.format);
+    }
+    /* If not - create MEM driver for intermediate dataset. 
+     * Check if raster can be created at all (with GDALCreateCopy) */
+    else if ((*pGDALGetMetadataItem)(driver, GDAL_DCAP_CREATECOPY, NULL)) {
+	GDALDriverH mem_driver;
+
+	G_message(_("Driver <%s> does not support direct writing. "
+		    "Using MEM driver for intermediate dataset."),
+		  st->opts.format);
+
+	mem_driver = (*pGDALGetDriverByName)("MEM");
+	if (!mem_driver)
+	    G_fatal_error(_("Unable to get in-memory raster driver"));
+
+	gdal->data = (*pGDALCreate)(mem_driver, "", G__.window.cols, G__.window.rows,
+				    1, gdal->type, st->opts.options);
+	if (!gdal->data)
+	    G_fatal_error(_("Unable to create <%s> dataset using memory driver"),
+			  name);
+    }
+    else
+	G_fatal_error(_("Driver <%s> does not support creating rasters"),
+		      st->opts.format);
+
+    gdal->band = (*pGDALGetRasterBand)(gdal->data, gdal->band_num);
+
+    (*pGDALSetRasterNoDataValue)(gdal->band, gdal->null_val);
+
+    /* Set Geo Transform  */
+    transform[0] = G__.window.west;
+    transform[1] = G__.window.ew_res;
+    transform[2] = 0.0;
+    transform[3] = G__.window.north;
+    transform[4] = 0.0;
+    transform[5] = -G__.window.ns_res;
+
+    if ((*pGDALSetGeoTransform)(gdal->data, transform) >= CE_Failure)
+	G_warning(_("Unable to set geo transform"));
+
+    if (st->srswkt)
+	if ((*pGDALSetProjection)(gdal->data, st->srswkt) == CE_Failure)
+	    G_warning(_("Unable to set projection"));
+
+    fp = G_fopen_new_misc("cell_misc", "gdal", name);
+    if (!fp)
+	G_fatal_error(_("Unable to create cell_misc/%s/gdal file"), name);
+
+    key_val = G_create_key_value();
+
+    G_set_key_value("file", gdal->filename, key_val);
+
+    sprintf(buf, "%d", gdal->band_num);
+    G_set_key_value("band", buf, key_val);
+
+    sprintf(buf, "%.22g", gdal->null_val);
+    G_set_key_value("null", buf, key_val);
+
+    sprintf(buf, "%d", gdal->type);
+    G_set_key_value("type", buf, key_val);
+
+    if (G_fwrite_key_value(fp, key_val) < 0)
+	G_fatal_error(_("Error writing cell_misc/%s/gdal file"), name);
+
+    G_free_key_value(key_val);
+
+    fclose(fp);
+
+    return gdal;
+#else
+    return NULL;
+#endif
+}
+
 void G_close_gdal_link(struct GDAL_link *gdal)
 {
 #ifdef GDAL_LINK
@@ -255,7 +488,34 @@
     G_free(gdal);
 }
 
+int G_close_gdal_write_link(struct GDAL_link *gdal)
+{
+    int stat = 1;
 #ifdef GDAL_LINK
+    GDALDriverH src_drv = (*pGDALGetDatasetDriver)(gdal->data);
+
+    if (G_strcasecmp((*pGDALGetDriverShortName)(src_drv), "MEM") == 0) {
+	GDALDriverH dst_drv = (*pGDALGetDriverByName)(st->opts.format);
+	GDALDatasetH dst = (*pGDALCreateCopy)(dst_drv, gdal->filename, gdal->data, FALSE,
+					      st->opts.options, NULL, NULL);
+	if (!dst) {
+	    G_warning(_("Unable to create output file <%s> using driver <%s>"),
+		      gdal->filename, st->opts.format);
+	    stat = -1;
+	}
+	(*pGDALClose)(dst);
+    }
+
+    (*pGDALClose)(gdal->data);
+
+#endif
+    G_free(gdal->filename);
+    G_free(gdal);
+
+    return stat;
+}
+
+#ifdef GDAL_LINK
 CPLErr G_gdal_raster_IO(
     GDALRasterBandH band, GDALRWFlag rw_flag,
     int x_off, int y_off, int x_size, int y_size,

Modified: grass/trunk/lib/gis/opencell.c
===================================================================
--- grass/trunk/lib/gis/opencell.c	2008-12-06 09:04:16 UTC (rev 34747)
+++ grass/trunk/lib/gis/opencell.c	2008-12-06 09:05:27 UTC (rev 34748)
@@ -487,6 +487,70 @@
     return G__open_raster_new(name, OPEN_NEW_UNCOMPRESSED, G__.fp_type);
 }
 
+#ifdef HAVE_GDAL
+static int G__open_raster_new_gdal(char *map, char *mapset, RASTER_MAP_TYPE map_type)
+{
+    int fd;
+    struct fileinfo *fcb;
+    int i;
+
+    /* dummy descriptor to reserve the fileinfo slot */
+    fd = open("/dev/null", O_RDONLY);
+    if (fd < 0)
+	return -1;
+
+    fcb = new_fileinfo(fd);
+
+    /* mark closed */
+    fcb->map_type = map_type;
+    fcb->open_mode = -1;
+
+    fcb->gdal = G_create_gdal_link(map, map_type);
+    if (!fcb->gdal)
+	return -1;
+
+    fcb->cellhd = G__.window;
+    fcb->cellhd.compressed = 0;
+    fcb->nbytes = G_raster_size(fcb->map_type);
+    /* for writing fcb->data is allocated to be G__.window.cols * 
+       sizeof(CELL or DCELL or FCELL)  */
+    fcb->data = G_calloc(G__.window.cols, fcb->nbytes);
+
+    fcb->name = map;
+    fcb->mapset = mapset;
+    fcb->cur_row = 0;
+
+    fcb->row_ptr = NULL;
+    fcb->temp_name = NULL;
+    fcb->null_temp_name = NULL;
+    fcb->null_cur_row = 0;
+    fcb->min_null_row = 0;
+    for (i = 0; i < NULL_ROWS_INMEM; i++)
+	fcb->NULL_ROWS[i] = NULL;
+
+    if (fcb->map_type != CELL_TYPE)
+	G_quant_init(&(fcb->quant));
+
+    /* init cell stats */
+    /* now works only for int maps */
+    if (fcb->map_type == CELL_TYPE)
+	if ((fcb->want_histogram = G__.want_histogram))
+	    G_init_cell_stats(&fcb->statf);
+
+    /* init range and if map is double/float init d/f_range */
+    G_init_range(&fcb->range);
+
+    if (fcb->map_type != CELL_TYPE)
+	G_init_fp_range(&fcb->fp_range);
+
+    /* mark file as open for write */
+    fcb->open_mode = OPEN_NEW_UNCOMPRESSED;
+    fcb->io_error = 0;
+
+    return fd;
+}
+#endif /* HAVE_GDAL */
+
 static int G__open_raster_new(const char *name, int open_mode,
 			      RASTER_MAP_TYPE map_type)
 {
@@ -532,6 +596,11 @@
     /* make sure window is set */
     G__init_window();
 
+#ifdef HAVE_GDAL
+    if (G_find_file2("", "GDAL", G_mapset()))
+	return G__open_raster_new_gdal(map, mapset, map_type);
+#endif
+
     /* open a tempfile name */
     tempname = G_tempfile();
     fd = creat(tempname, 0666);
@@ -553,6 +622,7 @@
     /* mark closed */
     fcb->map_type = map_type;
     fcb->open_mode = -1;
+    fcb->gdal = NULL;
 
     /* for writing fcb->data is allocated to be G__.window.cols * 
        sizeof(CELL or DCELL or FCELL)  */

Modified: grass/trunk/lib/gis/put_row.c
===================================================================
--- grass/trunk/lib/gis/put_row.c	2008-12-06 09:04:16 UTC (rev 34747)
+++ grass/trunk/lib/gis/put_row.c	2008-12-06 09:05:27 UTC (rev 34748)
@@ -59,7 +59,7 @@
  *
  ***********************************************************************
  *
- *  G__put_null_value_row(fd, buf)
+ *  put_null_value_row(fd, buf)
  *      int fd                  File descriptor where data is to be written
  *      char *buf               Buffer holding null data
  *
@@ -107,10 +107,13 @@
 
 /*--------------------------------------------------------------------------*/
 
-int G__put_null_value_row(int fd, const char *buf)
+static int put_null_value_row(int fd, const char *buf)
 {
     struct fileinfo *fcb = &G__.fileinfo[fd];
 
+    if (fcb->gdal)
+	G_fatal_error(_("GDAL output doesn't support writing null rows separately"));
+
     switch (put_null_data(fd, buf, fcb->null_cur_row)) {
     case -1:
 	return -1;
@@ -562,14 +565,71 @@
 
 /*--------------------------------------------------------------------------*/
 
+static int put_data_gdal(int fd, const void *rast, int row, int n,
+			 int zeros_r_nulls, RASTER_MAP_TYPE map_type)
+{
+#ifdef HAVE_GDAL
+    struct fileinfo *fcb = &G__.fileinfo[fd];
+    int size = G_raster_size(map_type);
+    DCELL null_val = fcb->gdal->null_val;
+    const void *src;
+    void *work_buf, *dst;
+    GDALDataType datatype;
+    CPLErr err;
+    int i;
+
+    if (row < 0 || row >= fcb->cellhd.rows)
+	return 0;
+
+    if (n <= 0)
+	return 0;
+
+    work_buf = G__alloca(n * size);
+
+    switch (map_type) {
+    case CELL_TYPE:	datatype = GDT_Int32;	break;
+    case FCELL_TYPE:	datatype = GDT_Float32;	break;
+    case DCELL_TYPE:	datatype = GDT_Float64;	break;
+    }
+
+    src = rast;
+    dst = work_buf;
+
+    for (i = 0; i < n; i++) {
+	if (G_is_null_value(src, map_type) || zeros_r_nulls && !*(CELL *)src)
+	    G_set_raster_value_d(dst, null_val, map_type);
+	else
+	    memcpy(dst, src, size);
+	src = G_incr_void_ptr(src, size);
+	dst = G_incr_void_ptr(dst, size);
+    }
+
+    err = G_gdal_raster_IO(fcb->gdal->band, GF_Write, 0, row, n, 1, work_buf,
+			   n, 1, datatype, 0, 0);
+
+    G__freea(work_buf);
+
+    return err == CE_None ? 1 : -1;
+#else
+    return -1;
+#endif
+}
+
 /*--------------------------------------------------------------------------*/
 
 /*--------------------------------------------------------------------------*/
 
+/*--------------------------------------------------------------------------*/
+
 static int put_raster_data(int fd, char *null_buf, const void *rast,
 			   int row, int n,
 			   int zeros_r_nulls, RASTER_MAP_TYPE map_type)
 {
+    struct fileinfo *fcb = &G__.fileinfo[fd];
+
+    if (fcb->gdal)
+	return put_data_gdal(fd, rast, row, n, zeros_r_nulls, map_type);
+
     return (map_type == CELL_TYPE)
 	? put_data(fd, null_buf, rast, row, n, zeros_r_nulls)
 	: put_fp_data(fd, null_buf, rast, row, n, map_type);
@@ -808,7 +868,10 @@
     fcb->cur_row++;
 
     /* write the null row for the data row */
-    stat = G__put_null_value_row(fd, null_buf);
+    if (fcb->gdal)
+	stat = 0;
+    else
+	stat = put_null_value_row(fd, null_buf);
     G__freea(null_buf);
     return stat;
 }

Modified: grass/trunk/raster/Makefile
===================================================================
--- grass/trunk/raster/Makefile	2008-12-06 09:04:16 UTC (rev 34747)
+++ grass/trunk/raster/Makefile	2008-12-06 09:05:27 UTC (rev 34748)
@@ -21,6 +21,7 @@
 	r.distance \
 	r.drain \
 	r.external \
+	r.external.out \
 	r.fill.dir \
 	r.flow \
 	r.grow.distance \


Property changes on: grass/trunk/raster/r.external.out
___________________________________________________________________
Name: svn:ignore
   + *OBJ*


Added: grass/trunk/raster/r.external.out/Makefile
===================================================================
--- grass/trunk/raster/r.external.out/Makefile	                        (rev 0)
+++ grass/trunk/raster/r.external.out/Makefile	2008-12-06 09:05:27 UTC (rev 34748)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ../..
+
+PGM  = r.external.out
+
+LIBES= $(GISLIB) $(GDALLIBS) $(GMATHLIB)
+DEPENDENCIES = $(GISDEP) $(GMATHDEP)
+EXTRA_INC = $(PROJINC) $(GDALCFLAGS)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+ifneq ($(USE_GDAL),)
+default: cmd
+endif

Added: grass/trunk/raster/r.external.out/main.c
===================================================================
--- grass/trunk/raster/r.external.out/main.c	                        (rev 0)
+++ grass/trunk/raster/r.external.out/main.c	2008-12-06 09:05:27 UTC (rev 34748)
@@ -0,0 +1,242 @@
+
+/****************************************************************************
+ *
+ * MODULE:       r.external.out
+ *               
+ * AUTHOR(S):    Glynn Clements, based on r.out.gdal
+ *
+ * PURPOSE:      Make GRASS write raster maps utilizing the GDAL library.
+ *
+ * COPYRIGHT:    (C) 2008 by Glynn Clements and the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <math.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/imagery.h>
+#include <grass/gprojects.h>
+#include <grass/glocale.h>
+
+#include "gdal.h"
+
+static void list_formats(void)
+{
+    /* -------------------------------------------------------------------- */
+    /*      List supported formats and exit.                                */
+    /*         code from GDAL 1.2.5  gcore/gdal_misc.cpp                    */
+    /*         Copyright (c) 1999, Frank Warmerdam                          */
+    /* -------------------------------------------------------------------- */
+    int iDr;
+
+    fprintf(stdout, _("Supported Formats:\n"));
+    for (iDr = 0; iDr < GDALGetDriverCount(); iDr++) {
+	GDALDriverH hDriver = GDALGetDriver(iDr);
+	const char *pszRWFlag;
+
+	if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL))
+	    pszRWFlag = "rw+";
+	else if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL))
+	    pszRWFlag = "rw";
+	else
+	    continue;
+
+	fprintf(stdout, "  %s (%s): %s\n",
+		GDALGetDriverShortName(hDriver),
+		pszRWFlag, GDALGetDriverLongName(hDriver));
+    }
+}
+
+static char *format_list(void)
+{
+    char *buf, *p;
+    int len = 0;
+    int first = 1;
+    int i;
+
+    for (i = 0; i < GDALGetDriverCount(); i++) {
+	GDALDriverH driver = GDALGetDriver(i);
+
+	if (!GDALGetMetadataItem(driver, GDAL_DCAP_CREATE, NULL) &&
+	    !GDALGetMetadataItem(driver, GDAL_DCAP_CREATECOPY, NULL))
+	    continue;
+
+	len += strlen(GDALGetDriverShortName(driver)) + 1;
+    }
+
+    buf = G_malloc(len);
+    p = buf;
+
+    for (i = 0; i < GDALGetDriverCount(); i++) {
+	GDALDriverH driver = GDALGetDriver(i);
+	const char *name;
+
+	if (!GDALGetMetadataItem(driver, GDAL_DCAP_CREATE, NULL) &&
+	    !GDALGetMetadataItem(driver, GDAL_DCAP_CREATECOPY, NULL))
+	    continue;
+
+	if (first)
+	    first = 0;
+	else
+	    *p++ = ',';
+
+	name = GDALGetDriverShortName(driver);
+	strcpy(p, name);
+	p += strlen(name);
+    }
+    *p++ = '\0';
+
+    return buf;
+}
+
+static void check_format(const char *format)
+{
+    GDALDriverH driver = GDALGetDriverByName(format);
+
+    if (!driver)
+	G_fatal_error(_("Format <%s> not supported"), format);
+
+    if (GDALGetMetadataItem(driver, GDAL_DCAP_CREATE, NULL))
+	return;
+
+    if (GDALGetMetadataItem(driver, GDAL_DCAP_CREATECOPY, NULL)) {
+	G_warning(_("Format <%s> does not support direct write"), format);
+	return;
+    }
+
+    G_fatal_error(_("Format <%s> does not support writing"), format);
+}
+
+static void make_link(const char *dir, const char *ext,
+		      const char *format, char **options)
+{
+    struct Key_Value *key_val = G_create_key_value();
+    char *opt_str = NULL;
+    FILE *fp;
+
+    if (options && *options) {
+	int n_opts = 0, opt_len = 0, i;
+	char *p;
+
+	for (i = 0; options[i]; i++) {
+	    n_opts++;
+	    opt_len += strlen(options[i]) + 1;
+	}
+
+	opt_str = G_malloc(opt_len);
+	p = opt_str;
+
+	for (i = 0; i < n_opts; i++) {
+	    if (i > 0)
+		*p++ = ',';
+	    strcpy(p, options[i]);
+	    p += strlen(options[i]);
+	}
+	*p++ = '\0';
+    }
+
+    if (ext && ext[0] != '.') {
+	char *p;
+	G_asprintf(&p, ".%s", ext);
+	ext = p;
+    }
+
+    if (dir)
+	G_set_key_value("directory", dir, key_val);
+    if (ext)
+	G_set_key_value("extension", ext, key_val);
+    if (format)
+	G_set_key_value("format", format, key_val);
+    if (opt_str)
+	G_set_key_value("options", opt_str, key_val);
+
+    fp = G_fopen_new("", "GDAL");
+    if (!fp)
+	G_fatal_error(_("Unable to create GDAL file"));
+
+    if (G_fwrite_key_value(fp, key_val) < 0)
+	G_fatal_error(_("Error writing GDAL file"));
+
+    fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
+    struct GModule *module;
+    struct {
+	struct Option *dir, *ext, *format, *opts;
+    } parm;
+    struct Flag *flag_f, *flag_r;
+
+    G_gisinit(argv[0]);
+
+    GDALAllRegister();
+
+    module = G_define_module();
+    module->keywords = _("raster, import");
+    module->description =
+	_("Link GDAL supported raster file to a binary raster map layer.");
+
+    parm.dir = G_define_option();
+    parm.dir->key = "directory";
+    parm.dir->description = _("Name of output directory");
+    parm.dir->required = NO;
+    parm.dir->type = TYPE_STRING;
+
+    parm.ext = G_define_option();
+    parm.ext->key = "extension";
+    parm.ext->description = _("Extension for output files");
+    parm.ext->required = NO;
+    parm.ext->type = TYPE_STRING;
+
+    parm.format = G_define_option();
+    parm.format->key = "format";
+    parm.format->description = _("Format of output files");
+    parm.format->required = NO;
+    parm.format->type = TYPE_STRING;
+    parm.format->options = format_list();
+
+    parm.opts = G_define_option();
+    parm.opts->key = "options";
+    parm.opts->description = _("Creation options");
+    parm.opts->required = NO;
+    parm.opts->multiple = YES;
+    parm.opts->type = TYPE_STRING;
+
+    flag_f = G_define_flag();
+    flag_f->key = 'f';
+    flag_f->description = _("List supported formats and exit");
+    flag_f->guisection = _("Print");
+
+    flag_r = G_define_flag();
+    flag_r->key = 'r';
+    flag_r->description = _("Cease using GDAL and revert to native output");
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    if (flag_f->answer) {
+	list_formats();
+	exit(EXIT_SUCCESS);
+    }
+
+    if (flag_r->answer) {
+	G_remove("", "GDAL");
+	exit(EXIT_SUCCESS);
+    }
+
+    if (parm.format->answer)
+	check_format(parm.format->answer);
+
+    make_link(parm.dir->answer, parm.ext->answer, parm.format->answer,
+	      parm.opts->answers);
+
+    exit(EXIT_SUCCESS);
+}
+

Added: grass/trunk/raster/r.external.out/r.external.out.html
===================================================================
--- grass/trunk/raster/r.external.out/r.external.out.html	                        (rev 0)
+++ grass/trunk/raster/r.external.out/r.external.out.html	2008-12-06 09:05:27 UTC (rev 34748)
@@ -0,0 +1,22 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.external.out</em> instructs GRASS to write raster maps as data
+files using GDAL.
+
+<h2>SEE ALSO</h2>
+<em>
+<a href="r.in.gdal.html">r.in.gdal</a>,
+<a href="r.out.gdal.html">r.in.gdal</a>,
+<a href="r.external.html">r.external</a>
+</em>
+
+<h2>REFERENCES</h2>
+
+GDAL Pages: <a href="http://www.gdal.org">http://www.gdal.org/</a><br>
+
+<h2>AUTHOR</h2>
+
+Glynn Clements
+
+<p>
+<i>Last changed: $Date: 2008-08-15 08:16:42 +0200 (Fri, 15 Aug 2008) $</i>



More information about the grass-commit mailing list