[GRASS-SVN] r45467 - in grass/branches/develbranch_6: include lib/gis lib/python raster/r.in.bin raster/r.out.bin

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Feb 26 15:31:24 EST 2011


Author: martinl
Date: 2011-02-26 12:31:24 -0800 (Sat, 26 Feb 2011)
New Revision: 45467

Added:
   grass/branches/develbranch_6/lib/gis/seek.c
   grass/branches/develbranch_6/lib/python/array.py
Modified:
   grass/branches/develbranch_6/include/gis.h
   grass/branches/develbranch_6/include/gisdefs.h
   grass/branches/develbranch_6/lib/python/Makefile
   grass/branches/develbranch_6/raster/r.in.bin/main.c
   grass/branches/develbranch_6/raster/r.out.bin/main.c
Log:
pythonlib: array.py backported from trunk
	   related r.in/out.bin sync'ed with trunk
	   G_fseek() and G_ftell() added


Modified: grass/branches/develbranch_6/include/gis.h
===================================================================
--- grass/branches/develbranch_6/include/gis.h	2011-02-26 20:14:51 UTC (rev 45466)
+++ grass/branches/develbranch_6/include/gis.h	2011-02-26 20:31:24 UTC (rev 45467)
@@ -53,6 +53,12 @@
 #define FALSE 0
 #endif
 
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+#define PRI_OFF_T	"lld"
+#else
+#define PRI_OFF_T	"ld"
+#endif
+
 #define MAXEDLINES  50
 #define RECORD_LEN  80
 #define NEWLINE     '\n'

Modified: grass/branches/develbranch_6/include/gisdefs.h
===================================================================
--- grass/branches/develbranch_6/include/gisdefs.h	2011-02-26 20:14:51 UTC (rev 45466)
+++ grass/branches/develbranch_6/include/gisdefs.h	2011-02-26 20:31:24 UTC (rev 45467)
@@ -1080,6 +1080,10 @@
 void G_rotate_around_point(double, double, double *, double *, double);
 void G_rotate_around_point_int(int, int, int *, int *, double);
 
+/* seek.c */
+off_t G_ftell(FILE *);
+void G_fseek(FILE *, off_t, int);
+
 /* sample.c */
 DCELL G_get_raster_sample_nearest(
     int, const struct Cell_head *, struct Categories *, double, double, int);

Copied: grass/branches/develbranch_6/lib/gis/seek.c (from rev 45464, grass/trunk/lib/gis/seek.c)
===================================================================
--- grass/branches/develbranch_6/lib/gis/seek.c	                        (rev 0)
+++ grass/branches/develbranch_6/lib/gis/seek.c	2011-02-26 20:31:24 UTC (rev 45467)
@@ -0,0 +1,60 @@
+/*!
+ * \file gis/seek.c
+ *
+ * \brief GIS Library - file seek routines
+ *
+ * (C) 2009-2010 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 for details.
+ *
+ * \author Glynn Clements
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+/*!
+  \brief Get the current file position of the stream.
+
+  \param fp file descriptor
+
+  \return file position
+  \return -1 on failure
+*/
+off_t G_ftell(FILE *fp)
+{
+#ifdef HAVE_FSEEKO
+    return ftello(fp);
+#else
+    return (off_t) ftell(fp);
+#endif     
+}
+
+/*!
+  \brief Change the file position of the stream.
+
+  The value of <i>whence</i> must be one of the constants `SEEK_SET',
+  `SEEK_CUR', or `SEEK_END', to indicate whether the <i>offset</i> is
+  relative to the beginning of the file, the current file position, or
+  the end of the file, respectively.
+
+  \param fp file descriptor
+  \param offset offset
+  \param whence
+*/
+void G_fseek(FILE *fp, off_t offset, int whence)
+{
+#ifdef HAVE_FSEEKO
+    if (fseeko(fp, offset, whence) != 0)
+	G_fatal_error(_("Unable to seek"));
+#else
+    long loff = (long) offset;
+    if ((off_t) loff != offset)
+	G_fatal_error(_("Seek offset out of range"));
+    if (fseek(fp, loff, whence) != 0)
+	G_fatal_error(_("Unable to seek"));
+#endif     
+}

Modified: grass/branches/develbranch_6/lib/python/Makefile
===================================================================
--- grass/branches/develbranch_6/lib/python/Makefile	2011-02-26 20:14:51 UTC (rev 45466)
+++ grass/branches/develbranch_6/lib/python/Makefile	2011-02-26 20:31:24 UTC (rev 45467)
@@ -10,7 +10,7 @@
 GDIR = $(PYDIR)/grass
 DSTDIR = $(GDIR)/script
 
-MODULES = core db raster vector setup
+MODULES = core db raster vector array setup
 
 PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
 PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)

Copied: grass/branches/develbranch_6/lib/python/array.py (from rev 45464, grass/trunk/lib/python/array.py)
===================================================================
--- grass/branches/develbranch_6/lib/python/array.py	                        (rev 0)
+++ grass/branches/develbranch_6/lib/python/array.py	2011-02-26 20:31:24 UTC (rev 45467)
@@ -0,0 +1,115 @@
+"""!@package grass.script.array
+
+ at brief GRASS Python scripting module
+
+Functions to use GRASS rasters with NumPy.
+
+Usage:
+
+ at code
+from grass.script import array as garray
+...
+ at endcode
+
+(C) 2010 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.
+
+ at author Glynn Clements
+"""
+
+import os
+import numpy
+
+import core as grass
+
+# i18N
+import gettext
+gettext.install('grasslibs', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
+
+class array(numpy.memmap):
+    def __new__(cls, dtype = numpy.double):
+	reg = grass.region()
+	r = reg['rows']
+	c = reg['cols']
+	shape = (r, c)
+
+	filename = grass.tempfile()
+
+	self = numpy.memmap.__new__(
+	    cls,
+	    filename = filename,
+	    dtype = dtype,
+	    mode = 'w+',
+	    shape = shape)
+
+	self.filename = filename
+	return self
+
+    def _close(self):
+	numpy.memmap._close(self)
+	if isinstance(self, array):
+	    grass.try_remove(self.filename)
+
+    def read(self, mapname, null = None):
+	kind = self.dtype.kind
+	size = self.dtype.itemsize
+
+	if kind == 'f':
+	    flags = 'f'
+	elif kind in 'biu':
+	    flags = 'i'
+	else:
+	    raise ValueError(_('invalid kind <%s>') % kind)
+
+	if size not in [1,2,4,8]:
+	    raise ValueError(_('invalid size <%d>') % size)
+
+	return grass.run_command(
+	    'r.out.bin',
+	    flags = flags,
+	    input = mapname,
+	    output = self.filename,
+	    bytes = size,
+	    null = null,
+	    quiet = True)
+	
+
+    def write(self, mapname, title = None, null = None, overwrite = None):
+	kind = self.dtype.kind
+	size = self.dtype.itemsize
+
+	if kind == 'f':
+	    if size == 4:
+		flags = 'f'
+	    elif size == 8:
+		flags = 'd'
+	    else:
+		raise ValueError(_('invalid FP size <%d>') % size)
+	    size = None
+	elif kind in 'biu':
+	    if size not in [1,2,4]:
+		raise ValueError(_('invalid integer size <%d>') % size)
+	    flags = None
+	else:
+	    raise ValueError(_('invalid kind <%s>') % kind)
+
+	reg = grass.region()
+
+	return grass.run_command(
+	    'r.in.bin',
+	    flags = flags,
+	    input = self.filename,
+	    output = mapname,
+	    title = title,
+	    bytes = size,
+	    anull = null,
+	    overwrite = overwrite,
+	    verbose = True,
+	    north = reg['n'],
+	    south = reg['s'],
+	    east  = reg['e'],
+	    west  = reg['w'],
+	    rows  = reg['rows'],
+	    cols  = reg['cols'])

Modified: grass/branches/develbranch_6/raster/r.in.bin/main.c
===================================================================
--- grass/branches/develbranch_6/raster/r.in.bin/main.c	2011-02-26 20:14:51 UTC (rev 45466)
+++ grass/branches/develbranch_6/raster/r.in.bin/main.c	2011-02-26 20:31:24 UTC (rev 45467)
@@ -14,106 +14,218 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include <grass/gis.h>
-#include "gmt_grd.h"
 #include <grass/glocale.h>
 
-typedef unsigned short uint16;
-typedef unsigned int uint32;
+#include "gmt_grd.h"
 
-static double nul_val;
+static void swap_2(void *p)
+{
+    unsigned char *q = p;
+    unsigned char t;
+    t = q[0]; q[0] = q[1]; q[1] = t;
+}
 
-static void SwabShort(uint16 * wp)
+static void swap_4(void *p)
 {
-    register char *cp = (char *)wp;
-    int t;
+    unsigned char *q = p;
+    unsigned char t;
+    t = q[0]; q[0] = q[3]; q[3] = t;
+    t = q[1]; q[1] = q[2]; q[2] = t;
+}
 
-    t = cp[1];
-    cp[1] = cp[0];
-    cp[0] = t;
+static void swap_8(void *p)
+{
+    unsigned char *q = p;
+    unsigned char t;
+    t = q[0]; q[0] = q[7]; q[7] = t;
+    t = q[1]; q[1] = q[6]; q[6] = t;
+    t = q[2]; q[2] = q[5]; q[5] = t;
+    t = q[3]; q[3] = q[4]; q[4] = t;
 }
 
-static void SwabLong(uint32 * lp)
+static void read_int(FILE *fp, int swap_flag, int *x)
 {
-    register char *cp = (char *)lp;
-    int t;
+    if (fread(x, 4, 1, fp) != 1)
+	G_fatal_error(_("Error reading data"));
 
-    t = cp[3];
-    cp[3] = cp[0];
-    cp[0] = t;
-    t = cp[2];
-    cp[2] = cp[1];
-    cp[1] = t;
+    if (swap_flag)
+	swap_4(x);
 }
 
-static void SwabFloat(float *fp)
+static void read_double(FILE *fp, int swap_flag, double *x)
 {
-    SwabLong((uint32 *) fp);
+    if (fread(x, 8, 1, fp) != 1)
+	G_fatal_error(_("Error reading data"));
+
+    if (swap_flag)
+	swap_8(x);
 }
 
-static void SwabDouble(double *dp)
+static void read_gmt_header(struct GRD_HEADER *header, int swap_flag, FILE *fp)
 {
-    register char *cp = (char *)dp;
-    int t;
+    read_int(fp, swap_flag, &header->nx);
+    read_int(fp, swap_flag, &header->ny);
+    read_int(fp, swap_flag, &header->node_offset);
 
-    t = cp[7];
-    cp[7] = cp[0];
-    cp[0] = t;
-    t = cp[6];
-    cp[6] = cp[1];
-    cp[1] = t;
-    t = cp[5];
-    cp[5] = cp[2];
-    cp[2] = t;
-    t = cp[4];
-    cp[4] = cp[3];
-    cp[3] = t;
+    read_double(fp, swap_flag, &header->x_min);
+    read_double(fp, swap_flag, &header->x_max);
+    read_double(fp, swap_flag, &header->y_min);
+    read_double(fp, swap_flag, &header->y_max);
+    read_double(fp, swap_flag, &header->z_min);
+    read_double(fp, swap_flag, &header->z_max);
+    read_double(fp, swap_flag, &header->x_inc);
+    read_double(fp, swap_flag, &header->y_inc);
+    read_double(fp, swap_flag, &header->z_scale_factor);
+    read_double(fp, swap_flag, &header->z_add_offset);
+
+    fread(&header->x_units, sizeof(char[GRD_UNIT_LEN]),    1, fp);
+    fread(&header->y_units, sizeof(char[GRD_UNIT_LEN]),    1, fp);
+    fread(&header->z_units, sizeof(char[GRD_UNIT_LEN]),    1, fp);
+    fread(&header->title,   sizeof(char[GRD_TITLE_LEN]),   1, fp);
+    fread(&header->command, sizeof(char[GRD_COMMAND_LEN]), 1, fp);
+    fread(&header->remark,  sizeof(char[GRD_REMARK_LEN]),  1, fp);
 }
 
+static void get_gmt_header(const struct GRD_HEADER *header, struct Cell_head *region)
+{
+    region->cols   = header->nx;
+    region->rows   = header->ny;
+    region->west   = header->x_min;
+    region->east   = header->x_max;
+    region->south  = header->y_min;
+    region->north  = header->y_max;
+    region->ew_res = header->x_inc;
+    region->ns_res = header->y_inc;
+}
+
+static void convert_cell(
+    DCELL *out_cell, unsigned char *in_cell,
+    int is_fp, int is_signed, int bytes, int swap_flag)
+{
+    if (swap_flag) {
+	switch (bytes) {
+	case 1:				break;
+	case 2:	swap_2(in_cell);	break;
+	case 4:	swap_4(in_cell);	break;
+	case 8:	swap_8(in_cell);	break;
+	}
+    }
+
+    if (is_fp) {
+	switch (bytes) {
+	case 4:
+	    *out_cell = (DCELL) *(float *) in_cell;
+	    break;
+	case 8:
+	    *out_cell = (DCELL) *(double *) in_cell;
+	    break;
+	}
+    }
+    else if (is_signed) {
+	switch (bytes) {
+	case 1:
+	    *out_cell = (DCELL) *(signed char *) in_cell;
+	    break;
+	case 2:
+	    *out_cell = (DCELL) *(short *) in_cell;
+	    break;
+	case 4:
+	    *out_cell = (DCELL) *(int *) in_cell;
+	    break;
+#ifdef HAVE_LONG_LONG_INT
+	case 8:
+	    *out_cell = (DCELL) *(long long *) in_cell;
+	    break;
+#endif
+	}
+    }
+    else {
+	switch (bytes) {
+	case 1:
+	    *out_cell = (DCELL) *(unsigned char *) in_cell;
+	    break;
+	case 2:
+	    *out_cell = (DCELL) *(unsigned short *) in_cell;
+	    break;
+	case 4:
+	    *out_cell = (DCELL) *(unsigned int *) in_cell;
+	    break;
+#ifdef HAVE_LONG_LONG_INT
+	case 8:
+	    *out_cell = (DCELL) *(unsigned long long *) in_cell;
+	    break;
+#endif
+	}
+    }
+}
+
+static void convert_row(
+    DCELL *raster, unsigned char *in_buf, int ncols,
+    int is_fp, int is_signed, int bytes, int swap_flag,
+    double null_val)
+{
+    unsigned char *ptr = in_buf;
+    int i;
+
+    for (i = 0; i < ncols; i++) {
+	DCELL x;
+	convert_cell(&x, ptr, is_fp, is_signed, bytes, swap_flag);
+	if (x == null_val)
+	    G_set_d_null_value(&raster[i], 1);
+	else
+	    raster[i] = x;
+	ptr += bytes;
+    }
+}
+
 int main(int argc, char *argv[])
 {
-    char *input;
-    char *output;
-    char *title;
-    FILE *fd;
-    int cf;
-    struct Cell_head cellhd;
-    struct History history;
-    CELL *cell;
-    FCELL *fcell;
-    DCELL *dcell;
-    RASTER_MAP_TYPE map_type;
-    int row, col;
-    int nrows = 0, ncols = 0;
-    int grass_nrows = 0, grass_ncols = 0;
-    int bytes, sflag, swap;
-    int no_coord = 0, no_dim = 0;
-    void *x_v;
-    char *x_c;
-    uint16 *x_s;
-    uint32 *x_i;
-    float *x_f;
-    double *x_d;
-    struct stat fileinfo;
-    int FILE_SIZE;
-    char *err;
-    char dummy[2];
-    struct GRD_HEADER header;
+    struct GModule *module;
     struct
     {
-	struct Option *input, *output, *title, *bytes,
-	    *north, *south, *east, *west, *rows, *cols, *anull;
+	struct Option *input;
+	struct Option *output;
+	struct Option *null;
+	struct Option *bytes;
+	struct Option *order;
+	struct Option *title;
+	struct Option *north;
+	struct Option *south;
+	struct Option *east;
+	struct Option *west;
+	struct Option *rows;
+	struct Option *cols;
     } parm;
     struct
     {
-	struct Flag *s, *f, *d, *b, *gmt_hd;
+	struct Flag *float_in;
+	struct Flag *double_in;
+	struct Flag *gmt_hd;
+	struct Flag *sign;
+	struct Flag *swap;
     } flag;
-    struct GModule *module;
-    union
-    {
-	int testWord;
-	char testByte[4];
-    } endianTest;
-    int swapFlag;
+    const char *input;
+    const char *output;
+    const char *title;
+    double null_val = 0;
+    int is_fp;
+    int is_signed;
+    int bytes;
+    int order;
+    int swap_flag;
+    struct Cell_head cellhd;
+    int nrows, ncols;
+    int grass_nrows, grass_ncols;
+    unsigned char *in_buf;
+    DCELL *out_buf;
+    RASTER_MAP_TYPE map_type;
+    int fd;
+    FILE *fp;
+    off_t file_size;
+    struct GRD_HEADER header;
+    int row;
+    struct History history;
+    off_t expected;
 
     G_gisinit(argv[0]);
 
@@ -121,29 +233,28 @@
     module = G_define_module();
     module->keywords = _("raster, import");
     module->description =
-	_("Import a binary raster file into a GRASS raster map layer.");
+	_("Import a binary raster file into a GRASS raster map.");
 
+    flag.float_in = G_define_flag();
+    flag.float_in->key = 'f';
+    flag.float_in->description =
+	_("Import as floating-point data (default: integer)");
 
-    flag.f = G_define_flag();
-    flag.f->key = 'f';
-    flag.f->description =
-	_("Import as Floating Point Data (default: Integer)");
+    flag.double_in = G_define_flag();
+    flag.double_in->key = 'd';
+    flag.double_in->description =
+	_("Import as double-precision floating-point data (default: integer)");
 
-    flag.d = G_define_flag();
-    flag.d->key = 'd';
-    flag.d->description =
-	_("Import as Double Precision Data (default: Integer)");
+    flag.sign = G_define_flag();
+    flag.sign->key = 's';
+    flag.sign->description = _("Signed data (two's complement)");
+    flag.sign->guisection = _("Settings");
 
-    flag.s = G_define_flag();
-    flag.s->key = 's';
-    flag.s->description = _("Signed data (high bit means negative value)");
-    flag.s->guisection = _("Settings");
+    flag.swap = G_define_flag();
+    flag.swap->key = 'b';
+    flag.swap->description = _("Byte Swap the Data During Import");
+    flag.swap->guisection = _("Settings");
 
-    flag.b = G_define_flag();
-    flag.b->key = 'b';
-    flag.b->description = _("Byte Swap the Data During Import");
-    flag.b->guisection = _("Settings");
-
     flag.gmt_hd = G_define_flag();
     flag.gmt_hd->key = 'h';
     flag.gmt_hd->description = _("Get region info from GMT style header");
@@ -160,7 +271,7 @@
 
     parm.title = G_define_option();
     parm.title->key = "title";
-    parm.title->key_desc = "\"phrase\"";
+    parm.title->key_desc = "phrase";
     parm.title->type = TYPE_STRING;
     parm.title->required = NO;
     parm.title->description = _("Title for resultant raster map");
@@ -168,11 +279,19 @@
     parm.bytes = G_define_option();
     parm.bytes->key = "bytes";
     parm.bytes->type = TYPE_INTEGER;
-    parm.bytes->answer = "1";
     parm.bytes->required = NO;
-    parm.bytes->description = _("Number of bytes per cell (1, 2, 4)");
+    parm.bytes->options = "1,2,4,8";
+    parm.bytes->description = _("Number of bytes per cell");
     parm.bytes->guisection = _("Settings");
 
+    parm.order = G_define_option();
+    parm.order->key = "order";
+    parm.order->type = TYPE_STRING;
+    parm.order->required = NO;
+    parm.order->options = "big,little,native,swap";
+    parm.order->description = _("Output byte order");
+    parm.order->answer = "native";
+
     parm.north = G_define_option();
     parm.north->key = "north";
     parm.north->type = TYPE_DOUBLE;
@@ -219,118 +338,97 @@
     parm.cols->description = _("Number of columns");
     parm.cols->guisection = _("Bounds");
 
-    parm.anull = G_define_option();
-    parm.anull->key = "anull";
-    parm.anull->type = TYPE_DOUBLE;
-    parm.anull->required = NO;
-    parm.anull->description = _("Set Value to NULL");
-    parm.anull->guisection = _("Settings");
+    parm.null = G_define_option();
+    parm.null->key = "anull";
+    parm.null->type = TYPE_DOUBLE;
+    parm.null->required = NO;
+    parm.null->description = _("Set Value to NULL");
+    parm.null->guisection = _("Settings");
 
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
     input = parm.input->answer;
     output = parm.output->answer;
-    if (title = parm.title->answer)
-	G_strip(title);
+    title = parm.title->answer;
 
-    if (flag.f->answer)
-	bytes = 4;
-    else if (flag.d->answer)
-	bytes = 8;
-    else if (sscanf(parm.bytes->answer, "%d%1s", &bytes, dummy) != 1)
-	G_fatal_error(_("Parsing bytes per cell"));
-    if (bytes <= 0)
-	G_fatal_error(_("Bad number of bytes per cell"));
-    sflag = flag.s->answer;
+    if (G_strcasecmp(parm.order->answer, "big") == 0)
+	order = 0;
+    else if (G_strcasecmp(parm.order->answer, "little") == 0)
+	order = 1;
+    else if (G_strcasecmp(parm.order->answer, "native") == 0)
+	order = G_is_little_endian() ? 1 : 0;
+    else if (G_strcasecmp(parm.order->answer, "swap") == 0)
+	order = G_is_little_endian() ? 0 : 1;
 
-    swap = 0;
-    if (flag.b->answer) {
-	swap = 1;
-	G_message(_("Byte Swapping Turned On."));
+    if (flag.swap->answer) {
+	if (strcmp(parm.order->answer, "native") != 0)
+	    G_fatal_error(_("order= and -b are mutually exclusive"));
+	order = G_is_little_endian() ? 0 : 1;
     }
 
-    /* Check Endian State of Host Computer */
-    endianTest.testWord = 1;
-    if (endianTest.testByte[0] == 1) {
-	swapFlag = 1;		/*true: little endian */
-	if (swap == 1)
-	    swapFlag = 0;	/* Swapping enabled */
+    swap_flag = order == (G_is_little_endian() ? 0 : 1);
+
+    is_signed = !!flag.sign->answer;
+
+    is_fp = 0;
+    bytes = 0;
+
+    if (parm.bytes->answer)
+	bytes = atoi(parm.bytes->answer);
+
+    if (flag.float_in->answer && flag.double_in->answer)
+	G_fatal_error(_("-f and -d are mutually exclusive"));
+
+    if (flag.float_in->answer) {
+	if (bytes && bytes < 4)
+	    G_fatal_error(_("-f incompatible with bytes=%d; must be 4 or 8"), bytes);
+	if (!bytes)
+	    bytes = 4;
+	is_fp = 1;
     }
-    else {
-	swapFlag = 0;
-	if (swap == 1)
-	    swapFlag = 1;	/* Swapping enabled */
+
+    if (flag.double_in->answer) {
+	if (bytes && bytes != 8)
+	    G_fatal_error(_("-d incompatible with bytes=%d; must be 8"), bytes);
+	if (!bytes)
+	    bytes = 8;
+	is_fp = 1;
     }
 
-    cellhd.zone = G_zone();
-    cellhd.proj = G_projection();
+    if (!is_fp && !bytes)
+	G_fatal_error(_("bytes= required for integer data"));
 
-    if (!flag.gmt_hd->answer) {	/* NO GMT header */
+#ifndef HAVE_LONG_LONG_INT
+    if (!is_fp && bytes > 4)
+	G_fatal_error(_("Integer input doesn't support size=8 in this build"));
+#endif
 
-	/* Check for optional parameters */
-	if (!parm.north->answer && !parm.south->answer && !parm.east->answer
-	    && !parm.west->answer) {
-	    no_coord = 1;
-	    /* No coordinates provided */
-	}
-	if (!parm.rows->answer && !parm.cols->answer) {
-	    no_dim = 1;
-	    /* No dimensions provided */
-	}
-	/* Done check */
+    if (bytes != 1 && bytes != 2 && bytes != 4 && bytes != 8)
+	G_fatal_error(_("bytes= must be 1, 2, 4 or 8"));
 
+    if (parm.null->answer)
+	null_val = atof(parm.null->answer);
 
-	/* CASE 0 - Not enough parameters - exit */
-	if (no_dim == 1 && no_coord == 1)
-	    G_fatal_error(_("Missing parameters ...\nMust provide at least"
-			    "[north= south= east= west=] OR [r=	c=]"));
+    cellhd.zone = G_zone();
+    cellhd.proj = G_projection();
 
-	/* CASE 1 - All parameters supplied */
-	if (no_coord == 0 && no_dim == 0) {	/* Get all parmameters */
-	    if (!parm.north->answer || !parm.south->answer ||
-		!parm.west->answer || !parm.east->answer)
-		G_fatal_error(_("You have to provide all limits of geographic region (n,s,e,w)"));
-	    if (!G_scan_northing(parm.north->answer, &cellhd.north, cellhd.proj))
-		G_fatal_error(_("Illegal north coordinate <%s>"), parm.north->answer);
-	    if (!G_scan_northing(parm.south->answer, &cellhd.south, cellhd.proj))
-		G_fatal_error(_("Illegal south coordinate <%s>"), parm.south->answer);
-	    if (!G_scan_easting(parm.east->answer, &cellhd.east, cellhd.proj))
-		G_fatal_error(_("Illegal east coordinate <%s>"), parm.east->answer);
-	    if (!G_scan_easting(parm.west->answer, &cellhd.west, cellhd.proj))
-		G_fatal_error(_("Illegal west coordinate <%s>"), parm.west->answer);
-	    if (sscanf(parm.rows->answer, "%d%1s", &cellhd.rows, dummy) != 1)
-		G_fatal_error(_("Illegal number of rows <%s>"), parm.rows->answer);
-	    if (sscanf(parm.cols->answer, "%d%1s", &cellhd.cols, dummy) != 1)
-		G_fatal_error(_("Illegal number of columns <%s>"), parm.cols->answer);
-	}
+    if (!flag.gmt_hd->answer) {
+	/* NO GMT header */
+	int num_bounds;
 
-	/* CASE 2 - Get only rows and columns and calculate N S E W */
-	/* Only works with resolution = 1 */
-	if (no_dim == 0 && no_coord == 1) {	/* Get rows and cols only */
-	    if (sscanf(parm.rows->answer, "%d%1s", &cellhd.rows, dummy) != 1
-		|| cellhd.rows <= 0)
-		G_fatal_error(_("Illegal number of rows <%s>"), parm.rows->answer);
-	    if (sscanf(parm.cols->answer, "%d%1s", &cellhd.cols, dummy) != 1
-		|| cellhd.cols <= 0)
-		G_fatal_error(_("Illegal number of columns <%s>"), parm.cols->answer);
-	    cellhd.north = (double)cellhd.rows;
-	    cellhd.south = 0.;
-	    cellhd.east = (double)cellhd.cols;
-	    cellhd.west = 0.;
-	    G_message(_("Using N=%f S=%f E=%f W=%f"), cellhd.north,
-		      cellhd.south, cellhd.east, cellhd.west);
-	}
+	if (!parm.rows->answer || !parm.cols->answer)
+	    G_fatal_error(_("Either -h or rows= and cols= must be given"));
 
+	num_bounds = !!parm.north->answer + !!parm.south->answer +
+	    !!parm.east->answer + !!parm.west->answer;
+	if (num_bounds != 0 && num_bounds != 4)
+	    G_fatal_error(_("Either all or none of north=, south=, east= and west= must be given"));
 
-	/* CASE 3 - Get only N S E & W */
-	/* No rows and columns supplied - calculate from parameters */
-	/* Assumes 1x1 resolution */
-	if (no_coord == 0 && no_dim == 1) {	/* Get n, s, e, w */
-	    if (!parm.north->answer || !parm.south->answer ||
-		!parm.west->answer || !parm.east->answer)
-		G_fatal_error(
-		    _("You have to provide all limits of geographic region (n,s,e,w)"));
+	cellhd.rows = atoi(parm.rows->answer);
+	cellhd.cols = atoi(parm.cols->answer);
+
+	if (num_bounds > 0) {
 	    if (!G_scan_northing(parm.north->answer, &cellhd.north, cellhd.proj))
 		G_fatal_error(_("Illegal north coordinate <%s>"), parm.north->answer);
 	    if (!G_scan_northing(parm.south->answer, &cellhd.south, cellhd.proj))
@@ -339,252 +437,90 @@
 		G_fatal_error(_("Illegal east coordinate <%s>"), parm.east->answer);
 	    if (!G_scan_easting(parm.west->answer, &cellhd.west, cellhd.proj))
 		G_fatal_error(_("Illegal west coordinate <%s>"), parm.west->answer);
-
-	    /* Calculate rows and cols */
-	    cellhd.rows = (int)cellhd.north - cellhd.south;
-	    cellhd.cols = (int)cellhd.east - cellhd.west;
-	    G_message(_("Using rows=%d cols=%d\n"), cellhd.rows, cellhd.cols);
-	}			/* DONE */
+	}
     }
 
+    fp = fopen(input, "rb");
+    if (!fp)
+	G_fatal_error(_("Unable to open <%s>"), input);
 
-    if (parm.anull->answer != NULL)
-	sscanf(parm.anull->answer, "%lf", &nul_val);
+    /* Find File Size in Byte and Check against byte size */
+    G_fseek(fp, 0, SEEK_END);
+    file_size = G_ftell(fp);
+    G_fseek(fp, 0, SEEK_SET);
 
-    fd = fopen(input, "r");
-    if (fd == NULL) {
-	perror(input);
-	G_usage();
-	exit(EXIT_FAILURE);
-    }
-
     /* Read binary GMT style header */
     if (flag.gmt_hd->answer) {
-	fread(&header.nx, sizeof(int), 1, fd);
-	fread(&header.ny, sizeof(int), 1, fd);
-	fread(&header.node_offset, sizeof(int), 1, fd);
-	if (swapFlag == 0)
-	    fread(&header.node_offset, sizeof(int), 1, fd);
+	read_gmt_header(&header, swap_flag, fp);
+	get_gmt_header(&header, &cellhd);
+    }
 
-	fread(&header.x_min, sizeof(double), 1, fd);
-	fread(&header.x_max, sizeof(double), 1, fd);
-	fread(&header.y_min, sizeof(double), 1, fd);
-	fread(&header.y_max, sizeof(double), 1, fd);
-	fread(&header.z_min, sizeof(double), 1, fd);
-	fread(&header.z_max, sizeof(double), 1, fd);
-	fread(&header.x_inc, sizeof(double), 1, fd);
-	fread(&header.y_inc, sizeof(double), 1, fd);
-	fread(&header.z_scale_factor, sizeof(double), 1, fd);
-	fread(&header.z_add_offset, sizeof(double), 1, fd);
+    /* Adjust Cell Header to New Values */
+    G_adjust_Cell_head(&cellhd, 1, 1);
 
-	fread(&header.x_units, sizeof(char[GRD_UNIT_LEN]), 1, fd);
-	fread(&header.y_units, sizeof(char[GRD_UNIT_LEN]), 1, fd);
-	fread(&header.z_units, sizeof(char[GRD_UNIT_LEN]), 1, fd);
-	fread(&header.title, sizeof(char[GRD_TITLE_LEN]), 1, fd);
-	fread(&header.command, sizeof(char[GRD_COMMAND_LEN]), 1, fd);
-	fread(&header.remark, sizeof(char[GRD_REMARK_LEN]), 1, fd);
+    if (cellhd.proj == PROJECTION_LL && cellhd.ew_res / cellhd.ns_res > 10.)
+	/* TODO: find a reasonable value */
+	G_warning(
+	    _("East-West (ewres: %f) and North-South (nwres: %f) "
+	      "resolution differ significantly. "
+	      "Did you assign east= and west= correctly?"),
+	    cellhd.ew_res, cellhd.ns_res);
 
-	cellhd.cols = header.nx;
-	cellhd.rows = header.ny;
-	cellhd.west = header.x_min;
-	cellhd.east = header.x_max;
-	cellhd.south = header.y_min;
-	cellhd.north = header.y_max;
-	cellhd.ew_res = header.x_inc;
-	cellhd.ns_res = header.y_inc;
+    grass_nrows = nrows = cellhd.rows;
+    grass_ncols = ncols = cellhd.cols;
 
-	if (swap == 1) {
-	    /* Swapping Header Values */
-	    SwabLong((uint32 *) & cellhd.cols);
-	    SwabLong((uint32 *) & cellhd.rows);
-	    SwabDouble(&cellhd.west);
-	    SwabDouble(&cellhd.east);
-	    SwabDouble(&cellhd.south);
-	    SwabDouble(&cellhd.north);
-	    SwabDouble(&cellhd.ew_res);
-	    SwabDouble(&cellhd.ns_res);
-	}
+    G_set_window(&cellhd);
 
-	/* Adjust Cell Header to match resolution */
-	if (err = G_adjust_Cell_head(&cellhd, 0, 0)) {
-	    G_fatal_error("%s", err);
-	    exit(EXIT_FAILURE);
-	}
-	nrows = header.ny;
-	ncols = header.nx;
-	grass_nrows = cellhd.rows;
-	grass_ncols = cellhd.cols;
-    }
-
-    if (!flag.gmt_hd->answer) {
-	/* Adjust Cell Header to New Values */
-	if (err = G_adjust_Cell_head(&cellhd, 1, 1)) {
-	    G_fatal_error("%s", err);
-	    exit(EXIT_FAILURE);
-	}
-	grass_nrows = nrows = cellhd.rows;
-	grass_ncols = ncols = cellhd.cols;
-    }
-
-    if (G_set_window(&cellhd) < 0)
-	exit(3);
-
     if (grass_nrows != G_window_rows())
-	G_fatal_error("rows changed from %d to %d\n", grass_nrows,
-		      G_window_rows());
+	G_fatal_error("rows changed from %d to %d",
+		      grass_nrows, G_window_rows());
 
     if (grass_ncols != G_window_cols())
-	G_fatal_error("cols changed from %d to %d\n", grass_ncols,
-		      G_window_cols());
+	G_fatal_error("cols changed from %d to %d",
+		      grass_ncols, G_window_cols());
 
+    expected = (off_t) ncols * nrows * bytes;
+    if (flag.gmt_hd->answer)
+	expected += 892;
 
-    /* Find File Size in Byte and Check against byte size */
-    if (stat(input, &fileinfo) < 0) {
-	perror("fstat");
-	exit(1);
+    if (file_size != expected) {
+	G_warning(_("File Size %"PRI_OFF_T" ... Total Bytes %"PRI_OFF_T),
+		  file_size, expected);
+	G_fatal_error(_("Bytes do not match file size"));
     }
-    FILE_SIZE = fileinfo.st_size;
 
-    if (flag.gmt_hd->answer) {
-	if (swapFlag == 0) {
-	    if (FILE_SIZE != (896 + (ncols * nrows * bytes))) {
-		G_warning(_("Bytes do not match File size"));
-		G_warning(_("File Size %d ... Total Bytes %d"), FILE_SIZE,
-			  896 + (ncols * nrows * bytes));
-		G_warning(_("Try bytes=%d or adjusting input parameters"),
-			  (FILE_SIZE - 896) / (ncols * nrows));
-		exit(EXIT_FAILURE);
-	    }
-	}
-	else {
-	    if (FILE_SIZE != (892 + (ncols * nrows * bytes))) {
-		G_warning(_("Bytes do not match File size"));
-		G_warning(_("File Size %d ... Total Bytes %d"), FILE_SIZE,
-			  892 + (ncols * nrows * bytes));
-		G_warning(_("Try bytes=%d or adjusting input parameters"),
-			  (FILE_SIZE - 892) / (ncols * nrows));
-		exit(EXIT_FAILURE);
-	    }
-	}
-    }
-    else {
-	/* No Header */
-	if (FILE_SIZE != (ncols * nrows * bytes)) {
-	    G_warning(_("Bytes do not match File size"));
-	    G_warning(_("File Size %d ... Total Bytes %d"), FILE_SIZE,
-		      ncols * nrows * bytes);
-	    G_warning(_("Try bytes=%d or adjusting input parameters"),
-		      FILE_SIZE / (ncols * nrows));
-	    exit(EXIT_FAILURE);
-	}
-    }
+    in_buf = G_malloc(ncols * bytes);
+    out_buf = G_allocate_d_raster_buf();
 
-    if (flag.f->answer) {
-	map_type = FCELL_TYPE;
-	fcell = G_allocate_f_raster_buf();
-    }
-    else if (flag.d->answer) {
-	map_type = DCELL_TYPE;
-	dcell = G_allocate_d_raster_buf();
-    }
-    else {
-	cell = G_allocate_c_raster_buf();
-	map_type = CELL_TYPE;
-    }
+    map_type = is_fp
+	? (bytes > 4
+	   ? DCELL_TYPE
+	   : FCELL_TYPE)
+	: CELL_TYPE;
 
-    cf = G_open_raster_new(output, map_type);
-    if (cf < 0) {
-	G_fatal_error(_("Unable to create raster map <%s>"), output);
-	exit(EXIT_FAILURE);
-    }
+    in_buf = G_malloc(ncols * bytes);
+    out_buf = G_allocate_d_raster_buf();
 
-    x_v = G_malloc(ncols * bytes);
-    x_f = (float *)x_v;
-    x_d = (double *)x_v;
-    x_i = (uint32 *) x_v;
-    x_s = (uint16 *) x_v;
-    x_c = (char *)x_v;
+    fd = G_open_raster_new(output, map_type);
 
-    if (cellhd.proj == PROJECTION_LL && cellhd.ew_res / cellhd.ns_res > 10.)	/* TODO: find a reasonable value */
-	G_warning(
-	   _("East-West (ewres: %f) and North-South (nwres: %f) "
-	     "resolution differ significantly. "
-	     "Did you assign east= and west= correctly?"),
-	     cellhd.ew_res, cellhd.ns_res);
-
     for (row = 0; row < grass_nrows; row++) {
-	if (fread(x_v, bytes * ncols, 1, fd) != 1) {
-	    G_unopen_cell(cf);
-	    G_fatal_error(_("Conversion failed at row %d"), row);
-	    exit(EXIT_FAILURE);
-	}
+	G_percent(row, nrows, 2);
 
-	for (col = 0; col < grass_ncols; col++) {
-	    if (flag.f->answer) {
-		/* Import Float */
-		if (swap)
-		    SwabFloat(&x_f[col]);
-		fcell[col] = (FCELL) x_f[col];
-	    }
-	    else if (flag.d->answer) {
-		/* Import Double */
-		if (swap)
-		    SwabDouble(&x_d[col]);
-		dcell[col] = (DCELL) x_d[col];
-	    }
-	    else if (bytes == 1) {
-		/* Import 1 byte Byte */
-		if (sflag)
-		    cell[col] = (CELL) (signed char)x_c[col];
-		else
-		    cell[col] = (CELL) (unsigned char)x_c[col];
-	    }
-	    else if (bytes == 2) {
-		/* Import 2 byte Short */
-		if (swap)
-		    SwabShort(&x_s[col]);
-		if (sflag)
-		    cell[col] = (CELL) (signed short)x_s[col];
-		else
-		    cell[col] = (CELL) (unsigned short)x_s[col];
-	    }
-	    else {
-		/* Import 4 byte Int */
-		if (swap)
-		    SwabLong(&x_i[col]);
-		if (sflag)
-		    cell[col] = (CELL) (signed int)x_i[col];
-		else
-		    cell[col] = (CELL) (unsigned int)x_i[col];
-	    }
-	    if (parm.anull->answer) {
-		if (flag.d->answer) {
-		    if (dcell[col] == nul_val)
-			G_set_d_null_value(&dcell[col], 1);
-		}
-		else if (flag.f->answer) {
-		    if (fcell[col] == (float)nul_val)
-			G_set_f_null_value(&fcell[col], 1);
-		}
-		else {
-		    if (cell[col] == (int)nul_val)
-			G_set_c_null_value(&cell[col], 1);
-		}
-	    }
-	}
+	if (fread(in_buf, bytes, ncols, fp) != ncols)
+	    G_fatal_error(_("Error reading data"));
 
-	if (flag.f->answer)
-	    G_put_f_raster_row(cf, fcell);
-	else if (flag.d->answer)
-	    G_put_d_raster_row(cf, dcell);
-	else
-	    G_put_c_raster_row(cf, cell);
+	convert_row(out_buf, in_buf, ncols, is_fp, is_signed,
+		    bytes, swap_flag, null_val);
 
-	G_percent(row + 1, nrows, 2);
+	G_put_d_raster_row(fd, out_buf);
     }
 
+    G_percent(row, nrows, 2);	/* finish it off */
+
+    G_close_cell(fd);
+    fclose(fp);
+
     G_debug(1, "Creating support files for %s", output);
-    G_close_cell(cf);
 
     if (title)
 	G_put_cell_title(output, title);
@@ -593,6 +529,5 @@
     G_command_history(&history);
     G_write_history(output, &history);
 
-
-    exit(EXIT_SUCCESS);
+    return EXIT_SUCCESS;
 }

Modified: grass/branches/develbranch_6/raster/r.out.bin/main.c
===================================================================
--- grass/branches/develbranch_6/raster/r.out.bin/main.c	2011-02-26 20:14:51 UTC (rev 45466)
+++ grass/branches/develbranch_6/raster/r.out.bin/main.c	2011-02-26 20:31:24 UTC (rev 45467)
@@ -1,8 +1,9 @@
 /*
  *   r.out.bin
  *
- *   Copyright (C) 2000 by the GRASS Development Team
+ *   Copyright (C) 2000,2010 by the GRASS Development Team
  *   Author: Bob Covill <bcovill at tekmap.ns.ca>
+ *   Modified by Glynn Clements, 2010-01-10
  *
  *   This program is free software under the GPL (>=v2)
  *   Read the file COPYING coming with GRASS for details.
@@ -13,55 +14,270 @@
 #include <stdlib.h>
 #include <string.h>
 #include <grass/gis.h>
+#include <grass/raster.h>
 #include <grass/glocale.h>
 
-#include "./gmt_grd.h"
-#include "./swab.h"
+#include "gmt_grd.h"
 
-int main(int argc, char *argv[])
+static void swap_2(void *p)
 {
-    void *raster, *ptr;
-    RASTER_MAP_TYPE out_type, map_type;
-    char *name;
-    char outfile[GNAME_MAX];
-    char *mapset;
-    int null_str = 0;
-    char buf[128];
-    int fd;
-    int row, col;
-    int nrows, ncols;
-    short number_i;
-    int do_stdout = 0;
-    int swapFlag;
-    FILE *fp;
-    struct GRD_HEADER header;
+    unsigned char *q = p;
+    unsigned char t;
+    t = q[0]; q[0] = q[1]; q[1] = t;
+}
+
+static void swap_4(void *p)
+{
+    unsigned char *q = p;
+    unsigned char t;
+    t = q[0]; q[0] = q[3]; q[3] = t;
+    t = q[1]; q[1] = q[2]; q[2] = t;
+}
+
+static void swap_8(void *p)
+{
+    unsigned char *q = p;
+    unsigned char t;
+    t = q[0]; q[0] = q[7]; q[7] = t;
+    t = q[1]; q[1] = q[6]; q[6] = t;
+    t = q[2]; q[2] = q[5]; q[5] = t;
+    t = q[3]; q[3] = q[4]; q[4] = t;
+}
+
+static void write_int(FILE *fp, int swap_flag, int x)
+{
+    if (swap_flag)
+	swap_4(&x);
+
+    if (fwrite(&x, 4, 1, fp) != 1)
+	G_fatal_error(_("Error writing data"));
+}
+
+static void write_double(FILE *fp, int swap_flag, double x)
+{
+    if (swap_flag)
+	swap_8(&x);
+
+    if (fwrite(&x, 8, 1, fp) != 1)
+	G_fatal_error(_("Error writing data"));
+}
+
+static void make_gmt_header(
+    struct GRD_HEADER *header,
+    const char *name, const char *outfile,
+    const struct Cell_head *region, double null_val)
+{
     struct FPRange range;
-    DCELL Z_MIN, Z_MAX;
+    DCELL z_min, z_max;
 
-    float number_f;
-    double number_d;
-    short null_val_i;
-    float null_val_f;
-    double null_val_d;
-    struct Cell_head region;
+    G_read_fp_range(name, "", &range);
+    G_get_fp_range_min_max(&range, &z_min, &z_max);
+
+    header->nx = region->cols;
+    header->ny = region->rows;
+    header->node_offset = 1;	/* 1 is pixel registration */
+    header->x_min = region->west;
+    header->x_max = region->east;
+    header->y_min = region->south;
+    header->y_max = region->north;
+    header->z_min = (double) z_min;
+    header->z_max = (double) z_max;
+    header->x_inc = region->ew_res;
+    header->y_inc = region->ns_res;
+    header->z_scale_factor = 1.0;
+    header->z_add_offset = 0.0;
+
+    if (region->proj == PROJECTION_LL) {
+	strcpy(header->x_units, "degrees");
+	strcpy(header->y_units, "degrees");
+    }
+    else {
+	strcpy(header->x_units, "Meters");
+	strcpy(header->y_units, "Meters");
+    }
+
+    strcpy(header->z_units, "elevation");
+    strcpy(header->title, name);
+    sprintf(header->command, "r.out.bin -h input=%s output=%s", name, outfile);
+    sprintf(header->remark, "%g used for NULL", null_val);
+}
+
+static void write_gmt_header(const struct GRD_HEADER *header, int swap_flag, FILE *fp)
+{
+    /* Write Values 1 at a time if byteswapping */
+    write_int(fp, swap_flag, header->nx);
+    write_int(fp, swap_flag, header->ny);
+    write_int(fp, swap_flag, header->node_offset);
+
+    write_double(fp, swap_flag, header->x_min);
+    write_double(fp, swap_flag, header->x_max);
+    write_double(fp, swap_flag, header->y_min);
+    write_double(fp, swap_flag, header->y_max);
+    write_double(fp, swap_flag, header->z_min);
+    write_double(fp, swap_flag, header->z_max);
+    write_double(fp, swap_flag, header->x_inc);
+    write_double(fp, swap_flag, header->y_inc);
+    write_double(fp, swap_flag, header->z_scale_factor);
+    write_double(fp, swap_flag, header->z_add_offset);
+
+    fwrite(header->x_units, sizeof(char[GRD_UNIT_LEN]),    1, fp);
+    fwrite(header->y_units, sizeof(char[GRD_UNIT_LEN]),    1, fp);
+    fwrite(header->z_units, sizeof(char[GRD_UNIT_LEN]),    1, fp);
+    fwrite(header->title,   sizeof(char[GRD_TITLE_LEN]),   1, fp);
+    fwrite(header->command, sizeof(char[GRD_COMMAND_LEN]), 1, fp);
+    fwrite(header->remark,  sizeof(char[GRD_REMARK_LEN]),  1, fp);
+}
+
+static void write_bil_hdr(
+    const char *outfile, const struct Cell_head *region,
+    int bytes, int order, int header, double null_val)
+{
+    char out_tmp[GPATH_MAX];
+    FILE *fp;
+
+    sprintf(out_tmp, "%s.hdr", outfile);
+    G_verbose_message(_("Header File = %s"), out_tmp);
+
+    /* Open Header File */
+    fp = fopen(out_tmp, "w");
+    if (!fp)
+	G_fatal_error(_("Unable to create file <%s>"), out_tmp);
+
+    fprintf(fp, "nrows %d\n", region->rows);
+    fprintf(fp, "ncols %d\n", region->cols);
+    fprintf(fp, "nbands 1\n");
+    fprintf(fp, "nbits %d\n", bytes * 8);
+    fprintf(fp, "byteorder %s\n", order == 0 ? "M" : "I");
+    fprintf(fp, "layout bil\n");
+    fprintf(fp, "skipbytes %d\n", header ? 892 : 0);
+    fprintf(fp, "nodata %g\n", null_val);
+
+    fclose(fp);
+}
+
+static void convert_cell(
+    unsigned char *out_cell, const DCELL in_cell,
+    int is_fp, int bytes, int swap_flag)
+{
+    if (is_fp) {
+	switch (bytes) {
+	case 4:
+	    *(float *) out_cell = (float) in_cell;
+	    break;
+	case 8:
+	    *(double *) out_cell = (double) in_cell;
+	    break;
+	}
+    }
+    else {
+	switch (bytes) {
+	case 1:
+	    *(unsigned char *) out_cell = (unsigned char) in_cell;
+	    break;
+	case 2:
+	    *(short *) out_cell = (short) in_cell;
+	    break;
+	case 4:
+	    *(int *) out_cell = (int) in_cell;
+	    break;
+#ifdef HAVE_LONG_LONG_INT
+	case 8:
+	    *(long long *) out_cell = (long long) in_cell;
+	    break;
+#endif
+	}
+    }
+
+    if (swap_flag) {
+	switch (bytes) {
+	case 1:				break;
+	case 2:	swap_2(out_cell);	break;
+	case 4:	swap_4(out_cell);	break;
+	case 8:	swap_8(out_cell);	break;
+	}
+    }
+}
+
+static void convert_row(
+    unsigned char *out_buf, const DCELL *raster, int ncols,
+    int is_fp, int bytes, int swap_flag, double null_val)
+{
+    unsigned char *ptr = out_buf;
+    int i;
+
+    for (i = 0; i < ncols; i++) {
+	DCELL x = G_is_d_null_value(&raster[i])
+	    ? null_val
+	    : raster[i];
+	convert_cell(ptr, x, is_fp, bytes, swap_flag);
+	ptr += bytes;
+    }
+}
+
+static void write_bil_wld(const char *outfile, const struct Cell_head *region)
+{
+    char out_tmp[GPATH_MAX];
+    FILE *fp;
+
+    sprintf(out_tmp, "%s.wld", outfile);
+    G_verbose_message(_("World File = %s"), out_tmp);
+
+    /* Open World File */
+    fp = fopen(out_tmp, "w");
+    if (!fp)
+	G_fatal_error(_("Unable to create file <%s>"), out_tmp);
+
+    fprintf(fp, "%f\n", region->ew_res);
+    fprintf(fp, "0.0\n");
+    fprintf(fp, "0.0\n");
+    fprintf(fp, "-%f\n", region->ns_res);
+    fprintf(fp, "%f\n", region->west + (region->ew_res / 2));
+    fprintf(fp, "%f\n", region->north - (region->ns_res / 2));
+
+    fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
     struct GModule *module;
     struct
     {
 	struct Option *input;
 	struct Option *output;
 	struct Option *null;
+	struct Option *bytes;
+	struct Option *order;
     } parm;
     struct
     {
-	struct Flag *int_out, *gmt_hd, *BIL_hd, *swap;
+	struct Flag *int_out;
+	struct Flag *float_out;
+	struct Flag *gmt_hd;
+	struct Flag *bil_hd;
+	struct Flag *swap;
     } flag;
+    char *name;
+    char *outfile;
+    double null_val;
+    int do_stdout;
+    int is_fp;
+    int bytes;
+    int order;
+    int swap_flag;
+    struct Cell_head region;
+    int nrows, ncols;
+    DCELL *in_buf;
+    unsigned char *out_buf;
+    int fd;
+    FILE *fp;
+    struct GRD_HEADER header;
+    int row;
 
-
     G_gisinit(argv[0]);
 
     module = G_define_module();
-    module->keywords = _("raster");
-    module->description = _("Exports a GRASS raster to a binary array.");
+    module->keywords = _("raster, export");
+    module->description = _("Exports a GRASS raster map to a binary array.");
 
     /* Define the different options */
 
@@ -81,23 +297,41 @@
 
     parm.null = G_define_option();
     parm.null->key = "null";
-    parm.null->type = TYPE_INTEGER;
+    parm.null->type = TYPE_DOUBLE;
     parm.null->required = NO;
     parm.null->answer = "0";
     parm.null->description = _("Value to write out for null");
 
+    parm.bytes = G_define_option();
+    parm.bytes->key = "bytes";
+    parm.bytes->type = TYPE_INTEGER;
+    parm.bytes->required = NO;
+    parm.bytes->options = "1,2,4,8";
+    parm.bytes->description = _("Number of bytes per cell");
+
+    parm.order = G_define_option();
+    parm.order->key = "order";
+    parm.order->type = TYPE_STRING;
+    parm.order->required = NO;
+    parm.order->options = "big,little,native,swap";
+    parm.order->description = _("Output byte order");
+    parm.order->answer = "native";
+
     flag.int_out = G_define_flag();
     flag.int_out->key = 'i';
-    flag.int_out->description =
-	_("Output integer category values, not cell values");
+    flag.int_out->description = _("Generate integer output");
 
+    flag.float_out = G_define_flag();
+    flag.float_out->key = 'f';
+    flag.float_out->description = _("Generate floating-point output");
+
     flag.gmt_hd = G_define_flag();
     flag.gmt_hd->key = 'h';
     flag.gmt_hd->description = _("Export array with GMT compatible header");
 
-    flag.BIL_hd = G_define_flag();
-    flag.BIL_hd->key = 'b';
-    flag.BIL_hd->description = _("Generate BIL world and header files");
+    flag.bil_hd = G_define_flag();
+    flag.bil_hd->key = 'b';
+    flag.bil_hd->description = _("Generate BIL world and header files");
 
     flag.swap = G_define_flag();
     flag.swap->key = 's';
@@ -106,313 +340,132 @@
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
-    if (sscanf(parm.null->answer, "%d", &null_str) != 1)
+    if (sscanf(parm.null->answer, "%lf", &null_val) != 1)
 	G_fatal_error(_("Invalid value for null (integers only)"));
 
     name = parm.input->answer;
 
     if (parm.output->answer)
-	G_strncpy(outfile, parm.output->answer, sizeof(outfile) - 1);
+	outfile = parm.output->answer;
     else {
-	G_strncpy(outfile, name, sizeof(outfile) - 1 - 4);
-	strcat(outfile, ".bin");
+	outfile = G_malloc(strlen(name) + 4 + 1);
+	sprintf(outfile, "%s.bin", name);
     }
 
-    if ((strcmp("-", outfile)) == 0)
-	do_stdout = 1;
+    if (G_strcasecmp(parm.order->answer, "big") == 0)
+	order = 0;
+    else if (G_strcasecmp(parm.order->answer, "little") == 0)
+	order = 1;
+    else if (G_strcasecmp(parm.order->answer, "native") == 0)
+	order = G_is_little_endian() ? 1 : 0;
+    else if (G_strcasecmp(parm.order->answer, "swap") == 0)
+	order = G_is_little_endian() ? 0 : 1;
 
-    G_get_window(&region);
+    if (flag.swap->answer) {
+	if (strcmp(parm.order->answer, "native") != 0)
+	    G_fatal_error(_("order= and -s are mutually exclusive"));
+	order = G_is_little_endian() ? 0 : 1;
+    }
 
-    mapset = G_find_cell(name, "");
+    swap_flag = order == (G_is_little_endian() ? 0 : 1);
 
-    if (mapset == NULL)
-	G_fatal_error(_("Raster map <%s> not found"), name);
+    do_stdout = strcmp("-", outfile) == 0;
 
-    fd = G_open_cell_old(name, mapset);
-    if (fd < 0)
-	G_fatal_error(_("Unable to open raster map <%s>"), name);
+    if (flag.int_out->answer && flag.float_out->answer)
+	G_fatal_error(_("-i and -f are mutually exclusive"));
 
-    map_type = G_get_raster_map_type(fd);
-    if (!flag.int_out->answer)
-	out_type = map_type;
+    fd = G_open_cell_old(name, "");
+
+    if (flag.int_out->answer)
+	is_fp = 0;
+    else if (flag.float_out->answer)
+	is_fp = 1;
     else
-	out_type = CELL_TYPE;
+	is_fp = G_get_raster_map_type(fd) != CELL_TYPE;
 
+    if (parm.bytes->answer)
+	bytes = atoi(parm.bytes->answer);
+    else if (is_fp)
+	bytes = 4;
+    else
+	bytes = 2;
+
+    if (is_fp && bytes < 4)
+	G_fatal_error(_("Floating-point output requires bytes=4 or bytes=8"));
+
+#ifndef HAVE_LONG_LONG_INT
+    if (!is_fp && bytes > 4)
+	G_fatal_error(_("Integer output doesn't support bytes=8 in this build"));
+#endif
+
+    G_get_window(&region);
+
     /* open bin file for writing */
     if (do_stdout)
 	fp = stdout;
     else if (NULL == (fp = fopen(outfile, "w")))
 	G_fatal_error(_("Unable to create file <%s>"), outfile);
 
-    /* Check Endian State of Host Computer */
-    if (G_is_little_endian()) {
-	swapFlag = 1;		/*true: little endian */
-	if (flag.swap->answer)
-	    swapFlag = 0;	/* Swapping enabled */
-    }
-    else {
-	swapFlag = 0;
-	if (flag.swap->answer)
-	    swapFlag = 1;	/* Swapping enabled */
-    }
-
-
     /* Set up Parameters for GMT header */
     if (flag.gmt_hd->answer) {
-	G_read_fp_range(name, mapset, &range);
-	G_get_fp_range_min_max(&range, &Z_MIN, &Z_MAX);
-
-	header.nx = region.cols;
-	header.ny = region.rows;
-	header.node_offset = 1;	/* 1 is pixel registration */
-	header.x_min = (double)region.west;
-	header.x_max = (double)region.east;
-	header.y_min = (double)region.south;
-	header.y_max = (double)region.north;
-	header.z_min = (double)Z_MIN;
-	header.z_max = (double)Z_MAX;
-	header.x_inc = (double)region.ew_res;
-	header.y_inc = (double)region.ns_res;
-	header.z_scale_factor = (double)1.0;
-	header.z_add_offset = (double)0.0;
-
-	/* Swap Header if Required */
-	if (flag.swap->answer) {
-	    G_message(_("Swapping header data"));
-	    TIFFSwabLong((uint32 *) & header.nx);
-	    TIFFSwabLong((uint32 *) & header.ny);
-	    TIFFSwabLong((uint32 *) & header.node_offset);
-
-	    TIFFSwabDouble((double *)&header.x_min);
-	    TIFFSwabDouble((double *)&header.x_max);
-	    TIFFSwabDouble((double *)&header.y_min);
-	    TIFFSwabDouble((double *)&header.y_max);
-	    TIFFSwabDouble((double *)&header.z_min);
-	    TIFFSwabDouble((double *)&header.z_max);
-	    TIFFSwabDouble((double *)&header.x_inc);
-	    TIFFSwabDouble((double *)&header.y_inc);
-	    TIFFSwabDouble((double *)&header.z_scale_factor);
-	    TIFFSwabDouble((double *)&header.z_add_offset);
-	}
-
-	if (region.proj == PROJECTION_LL) {
-	    strcpy(header.x_units, "degrees");
-	    strcpy(header.y_units, "degrees");
-	}
-	else {
-	    strcpy(header.x_units, "Meters");
-	    strcpy(header.y_units, "Meters");
-	}
-	strcpy(header.z_units, "elevation");
-	strcpy(header.title, name);
-	strcpy(header.command, "r.out.bin -h input=");
-	strcat(header.command, name);
-	strcat(header.command, " output=");
-	strcat(header.command, outfile);
-	if (flag.swap->answer)
-	    TIFFSwabLong((uint32 *) & null_str);
-	sprintf(buf, "%d", null_str);
-	strcpy(header.remark, buf);
-	strcat(header.remark, " used for NULL");
+	if (!is_fp && bytes > 4)
+	    G_fatal_error(_("GMT grid doesn't support 64-bit integers"));
+	make_gmt_header(&header, name, outfile, &region, null_val);
     }
 
     /* Write out BIL support files compatible with Arc-View */
-    if (flag.BIL_hd->answer) {
-	char out_tmp1[GPATH_MAX], out_tmp2[GPATH_MAX];
-	FILE *fp_1, *fp_2;
-
-	strcpy(out_tmp1, outfile);
-	strcat(out_tmp1, ".hdr");
-	strcpy(out_tmp2, outfile);
-	strcat(out_tmp2, ".wld");
-
-	/* Open Header File */
-	if (NULL == (fp_1 = fopen(out_tmp1, "w")))
-	    G_fatal_error(_("Unable to create file <%s>"), out_tmp1);
-
-	/* Open World File */
-	if (NULL == (fp_2 = fopen(out_tmp2, "w")))
-	    G_fatal_error(_("Unable to create file <%s>"), out_tmp2);
-
-
+    if (flag.bil_hd->answer) {
 	G_message(_("Creating BIL support files..."));
-	G_message(_("Header File = %s"), out_tmp1);
-	G_message(_("World File = %s"), out_tmp2);
-
-	fprintf(fp_1, "nrows %d\n", region.rows);
-	fprintf(fp_1, "ncols %d\n", region.cols);
-	fprintf(fp_1, "nbands 1\n");
-
-	if (out_type == CELL_TYPE)
-	    fprintf(fp_1, "nbits 16\n");
-	if (out_type == FCELL_TYPE)
-	    fprintf(fp_1, "nbits 32\n");
-	if (out_type == DCELL_TYPE)
-	    fprintf(fp_1, "nbits 64\n");
-	if (swapFlag == 1)
-	    fprintf(fp_1, "byteorder I\n");	/* Intel - little endian */
-	if (swapFlag == 0)
-	    fprintf(fp_1, "byteorder M\n");	/* Motorola - big endian */
-
-	fprintf(fp_1, "layout bil\n");
-
-	if (flag.gmt_hd->answer) {
-	    if (swapFlag == 1)
-		fprintf(fp_1, "skipbytes 892\n");	/* Real size of struct - little endian */
-	    else
-		fprintf(fp_1, "skipbytes 896\n");	/* Pad size of struct - big endian */
-	}
-	else
-	    fprintf(fp_1, "skipbytes 0\n");
-
-	fprintf(fp_1, "nodata %d\n", null_str);
-
-	fclose(fp_1);
-
-	fprintf(fp_2, "%f\n", region.ew_res);
-	fprintf(fp_2, "0.0\n");
-	fprintf(fp_2, "0.0\n");
-	fprintf(fp_2, "-%f\n", region.ns_res);
-	fprintf(fp_2, "%f\n", region.west + (region.ew_res / 2));
-	fprintf(fp_2, "%f\n", region.north - (region.ns_res / 2));
-
-	fclose(fp_2);
+	write_bil_hdr(outfile, &region,
+		      bytes, order, flag.gmt_hd->answer, null_val);
+	write_bil_wld(outfile, &region);
     }
 
-    raster = G_allocate_raster_buf(out_type);
-
     /* Write out GMT Header if required */
-    if (flag.gmt_hd->answer) {
-	/* Write Values 1 at a time if byteswapping */
-	fwrite(&header.nx, sizeof(int), 1, fp);
-	fwrite(&header.ny, sizeof(int), 1, fp);
-	fwrite(&header.node_offset, sizeof(int), 1, fp);
-	if (swapFlag == 0)	/* Padding needed for big-endian */
-	    fwrite(&header.node_offset, sizeof(int), 1, fp);
+    if (flag.gmt_hd->answer)
+	write_gmt_header(&header, swap_flag, fp);
 
-	fwrite(&header.x_min, sizeof(double), 1, fp);
-	fwrite(&header.x_max, sizeof(double), 1, fp);
-	fwrite(&header.y_min, sizeof(double), 1, fp);
-	fwrite(&header.y_max, sizeof(double), 1, fp);
-	fwrite(&header.z_min, sizeof(double), 1, fp);
-	fwrite(&header.z_max, sizeof(double), 1, fp);
-	fwrite(&header.x_inc, sizeof(double), 1, fp);
-	fwrite(&header.y_inc, sizeof(double), 1, fp);
-	fwrite(&header.z_scale_factor, sizeof(double), 1, fp);
-	fwrite(&header.z_add_offset, sizeof(double), 1, fp);
-
-	fwrite(&header.x_units, sizeof(char[GRD_UNIT_LEN]), 1, fp);
-	fwrite(&header.y_units, sizeof(char[GRD_UNIT_LEN]), 1, fp);
-	fwrite(&header.z_units, sizeof(char[GRD_UNIT_LEN]), 1, fp);
-	fwrite(&header.title, sizeof(char[GRD_TITLE_LEN]), 1, fp);
-	fwrite(&header.command, sizeof(char[GRD_COMMAND_LEN]), 1, fp);
-	fwrite(&header.remark, sizeof(char[GRD_REMARK_LEN]), 1, fp);
-    }
-
     nrows = G_window_rows();
     ncols = G_window_cols();
 
-    if (out_type == CELL_TYPE) {
-	G_message(_("Exporting raster as integer values (bytes=%d)"),
-		  sizeof(short));
+    in_buf = G_allocate_d_raster_buf();
+    out_buf = G_malloc(ncols * bytes);
+
+    if (is_fp) {
+	G_message(_("Exporting raster as floating values (bytes=%d)"), bytes);
 	if (flag.gmt_hd->answer)
-	    G_message(_("Writing GMT integer format ID=2"));
+	    G_message(_("Writing GMT float format ID=1"));
     }
-    if (out_type == FCELL_TYPE) {
-	G_message(_("Exporting raster as floating values (bytes=%d)"),
-		  sizeof(float));
+    else {
+	G_message(_("Exporting raster as integer values (bytes=%d)"), bytes);
 	if (flag.gmt_hd->answer)
-	    G_message(_("Writing GMT float format ID=1"));
+	    G_message(_("Writing GMT integer format ID=2"));
     }
-    if (out_type == DCELL_TYPE)
-	G_message(_("Exporting raster as double values (bytes=%d)"),
-		  sizeof(double));
 
-    G_message(_("Using the current region settings..."));
-    G_message(_("north=%f"), region.north);
-    G_message(_("south=%f"), region.south);
-    G_message(_("east=%f"), region.east);
-    G_message(_("west=%f"), region.west);
-    G_message(_("r=%d"), region.rows);
-    G_message(_("c=%d"), region.cols);
+    G_verbose_message(_("Using the current region settings..."));
+    G_verbose_message(_("north=%f"), region.north);
+    G_verbose_message(_("south=%f"), region.south);
+    G_verbose_message(_("east=%f"), region.east);
+    G_verbose_message(_("west=%f"), region.west);
+    G_verbose_message(_("r=%d"), region.rows);
+    G_verbose_message(_("c=%d"), region.cols);
 
     for (row = 0; row < nrows; row++) {
-	if (G_get_raster_row(fd, raster, row, out_type) < 0)
-	    G_fatal_error(_("Reading map"));
 	G_percent(row, nrows, 2);
 
-	for (col = 0, ptr = raster; col < ncols; col++,
-	     ptr = G_incr_void_ptr(ptr, G_raster_size(out_type))) {
-	    if (!G_is_null_value(ptr, out_type)) {
-		if (out_type == CELL_TYPE) {
-		    number_i = *((CELL *) ptr);
-		    if (flag.swap->answer)
-			TIFFSwabShort((uint16 *) & number_i);
-		    fwrite(&number_i, sizeof(short), 1, fp);
-		}
-		else if (out_type == FCELL_TYPE) {
-		    number_f = *((FCELL *) ptr);
-		    if (flag.swap->answer)
-			TIFFSwabLong((uint32 *) & number_f);
-		    fwrite(&number_f, sizeof(float), 1, fp);
-		}
-		else if (out_type == DCELL_TYPE) {
-		    number_d = *((DCELL *) ptr);
-		    if (flag.swap->answer)
-			TIFFSwabDouble((double *)&number_d);
-		    fwrite(&number_d, sizeof(double), 1, fp);
-		}
-	    }
-	    else {
-		if (out_type == CELL_TYPE) {
-		    null_val_i = (int)null_str;
-		    if (flag.swap->answer)
-			TIFFSwabShort((uint16 *) & null_val_i);
-		    fwrite(&null_val_i, sizeof(short), 1, fp);
-		}
-		if (out_type == FCELL_TYPE) {
-		    null_val_f = (float)null_str;
-		    if (flag.swap->answer)
-			TIFFSwabLong((uint32 *) & null_val_f);
-		    fwrite(&null_val_f, sizeof(float), 1, fp);
-		}
-		if (out_type == DCELL_TYPE) {
-		    null_val_d = (double)null_str;
-		    if (flag.swap->answer)
-			TIFFSwabDouble((double *)&null_val_d);
-		    fwrite(&null_val_d, sizeof(double), 1, fp);
-		}
+	G_get_d_raster_row(fd, in_buf, row);
 
-	    }
-	}
+	convert_row(out_buf, in_buf, ncols, is_fp, bytes, swap_flag, null_val);
+
+	if (fwrite(out_buf, bytes, ncols, fp) != ncols)
+	    G_fatal_error(_("Error writing data"));
     }
+
     G_percent(row, nrows, 2);	/* finish it off */
 
     G_close_cell(fd);
     fclose(fp);
 
-    exit(EXIT_SUCCESS);
+    return EXIT_SUCCESS;
 }
 
-#ifdef UNUSED
-int set_type(char *str, RASTER_MAP_TYPE * out_type)
-{
-    char *ch;
-
-    ch = str;
-    if (*ch != '%')
-	G_fatal_error("wrong format: %s", str);
-
-    while (*(++ch)) ;
-    ch--;
-    if (*ch == 'd' || *ch == 'i' || *ch == 'o' || *ch == 'u' || *ch == 'x' ||
-	*ch == 'X')
-	*out_type = CELL_TYPE;
-    else if (*ch == 'f' || *ch == 'e' || *ch == 'E' || *ch == 'g' ||
-	     *ch == 'G')
-	*out_type = DCELL_TYPE;
-    /*      *out_type = FCELL_TYPE; */
-
-    return 0;
-}
-#endif



More information about the grass-commit mailing list