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; struct Option *north; struct Option *south; struct Option *top; struct Option *bottom; struct Option *east; struct Option *west; struct Option *rows; struct Option *cols; struct Option *depths; } parm; struct { struct Flag *integer_in; struct Flag *sign; struct Flag *depth; struct Flag *row; } flag; const char *input; const char *output; int is_integer; int is_signed; int bytes; int order; int byte_swap; RASTER_MAP_TYPE map_type; off_t file_size; struct History history; off_t expected; /* Need to be allocated later */ in_cell = NULL; G_gisinit(argv[0]); /* Set description */ module = G_define_module(); G_add_keyword(_("raster3d")); G_add_keyword(_("import")); G_add_keyword(_("voxel")); module->description = _("Imports a binary raster file into a GRASS 3D raster map."); parm.input = G_define_standard_option(G_OPT_F_BIN_INPUT); parm.input->description = _("Name of binary 3D raster file to be imported"); parm.output = G_define_standard_option(G_OPT_R3_OUTPUT); parm.bytes = G_define_option(); parm.bytes->key = "bytes"; parm.bytes->type = TYPE_INTEGER; parm.bytes->required = YES; parm.bytes->options = "1,2,4,8"; parm.bytes->description = _("Number of bytes per cell in binary file"); 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 = _("Byte order in binary file"); parm.order->answer = "native"; parm.north = G_define_option(); parm.north->key = "north"; parm.north->type = TYPE_DOUBLE; parm.north->required = YES; parm.north->description = _("Northern limit of geographic region (outer edge)"); parm.north->guisection = _("Bounds"); parm.south = G_define_option(); parm.south->key = "south"; parm.south->type = TYPE_DOUBLE; parm.south->required = YES; parm.south->description = _("Southern limit of geographic region (outer edge)"); parm.south->guisection = _("Bounds"); parm.east = G_define_option(); parm.east->key = "east"; parm.east->type = TYPE_DOUBLE; parm.east->required = YES; parm.east->description = _("Eastern limit of geographic region (outer edge)"); parm.east->guisection = _("Bounds"); parm.west = G_define_option(); parm.west->key = "west"; parm.west->type = TYPE_DOUBLE; parm.west->required = YES; parm.west->description = _("Western limit of geographic region (outer edge)"); parm.west->guisection = _("Bounds"); parm.bottom = G_define_option(); parm.bottom->key = "bottom"; parm.bottom->type = TYPE_DOUBLE; parm.bottom->required = YES; parm.bottom->description = _("Bottom limit of geographic region (outer edge)"); parm.bottom->guisection = _("Bounds"); parm.top = G_define_option(); parm.top->key = "top"; parm.top->type = TYPE_DOUBLE; parm.top->required = YES; parm.top->description = _("Top limit of geographic region (outer edge)"); parm.top->guisection = _("Bounds"); parm.rows = G_define_option(); parm.rows->key = "rows"; parm.rows->type = TYPE_INTEGER; parm.rows->required = YES; parm.rows->description = _("Number of rows"); parm.rows->guisection = _("Bounds"); parm.cols = G_define_option(); parm.cols->key = "cols"; parm.cols->type = TYPE_INTEGER; parm.cols->required = YES; parm.cols->description = _("Number of columns"); parm.cols->guisection = _("Bounds"); parm.depths = G_define_option(); parm.depths->key = "depths"; parm.depths->type = TYPE_INTEGER; parm.depths->required = YES; parm.depths->description = _("Number of depths"); parm.depths->guisection = _("Bounds"); parm.null = G_define_option(); parm.null->key = "null"; parm.null->type = TYPE_DOUBLE; parm.null->required = NO; parm.null->description = _("Set Value to NULL"); flag.row = G_define_flag(); flag.row->key = 'r'; flag.row->description = _("Switch the row order in output from " "north->south to south->north"); flag.depth = G_define_flag(); flag.depth->key = 'd'; flag.depth->description = _("Switch the depth order in output " "from bottom->top to top->bottom"); flag.integer_in = G_define_flag(); flag.integer_in->key = 'i'; flag.integer_in->description = _("Binary data is of type integer"); flag.sign = G_define_flag(); flag.sign->key = 's'; flag.sign->description = _("Signed data (two's complement)"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); input = parm.input->answer; output = parm.output->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; byte_swap = order == (G_is_little_endian() ? 0 : 1); is_signed = !!flag.sign->answer; is_integer = 0; bytes = 8; if (parm.bytes->answer) bytes = atoi(parm.bytes->answer); if (!flag.integer_in->answer) { if (bytes && bytes < 4) G_fatal_error( _("bytes=%d; must be 4 or 8 in case of floating point input"), bytes); if (!bytes) bytes = 4; } else { is_integer = 1; } #ifndef HAVE_LONG_LONG_INT if (is_integer && bytes > 4) G_fatal_error(_("Integer input doesn't support size=8 in this build")); #endif if (bytes != 1 && bytes != 2 && bytes != 4 && bytes != 8) G_fatal_error(_("bytes= must be 1, 2, 4 or 8")); region.zone = G_zone(); region.proj = G_projection(); region.rows = atoi(parm.rows->answer); region.cols = atoi(parm.cols->answer); region.depths = atoi(parm.depths->answer); region.top = atof(parm.top->answer); region.bottom = atof(parm.bottom->answer); if (!G_scan_northing(parm.north->answer, ®ion.north, region.proj)) G_fatal_error(_("Illegal north coordinate <%s>"), parm.north->answer); if (!G_scan_northing(parm.south->answer, ®ion.south, region.proj)) G_fatal_error(_("Illegal south coordinate <%s>"), parm.south->answer); if (!G_scan_easting(parm.east->answer, ®ion.east, region.proj)) G_fatal_error(_("Illegal east coordinate <%s>"), parm.east->answer); if (!G_scan_easting(parm.west->answer, ®ion.west, region.proj)) G_fatal_error(_("Illegal west coordinate <%s>"), parm.west->answer); Rast3d_adjust_region(®ion); expected = (off_t) region.rows * region.cols * region.depths * bytes; fp = fopen(input, "rb"); if (!fp) G_fatal_error(_("Unable to open <%s>"), input); /* 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); if (file_size != expected) { G_warning(_("File Size %lld ... Total Bytes %lld"), (long long int) file_size, (long long int) expected); G_fatal_error(_("Bytes do not match file size")); } map_type = (bytes > 4 ? DCELL_TYPE : FCELL_TYPE); if(is_integer && bytes >= 4) map_type = DCELL_TYPE; Rast3d_init_defaults(); /*Open the new 3D raster map */ map = Rast3d_open_new_opt_tile_size(output, RASTER3D_USE_CACHE_DEFAULT, ®ion, map_type, 32); if (map == NULL) G_fatal_error(_("Unable to open 3D raster map")); in_cell = G_malloc(bytes); bin_to_raster3d(parm.null->answer, map_type, is_integer, is_signed, bytes, byte_swap, flag.row->answer, flag.depth->answer); if (!Rast3d_close(map)) G_fatal_error(_("Unable to close 3D raster map")); /* write input name to map history */ Rast3d_read_history(output, G_mapset(), &history); Rast_set_history(&history, HIST_DATSRC_1, input); Rast3d_write_history(output, &history); fclose(fp); if (in_cell) G_free(in_cell); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { int i, row, col; /* counters */ unsigned long filesize; int endianness; /* 0=little, 1=big */ int data_format; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int (ie text) */ int data_type; /* 0=numbers 1=text */ int format_block; /* combo of endianness, 0, data_format, and type */ int realflag = 0; /* 0=only real values used */ /* should type be specifically uint32 ??? */ char array_name[32]; /* variable names must start with a letter (case sensitive) followed by letters, numbers, or underscores. 31 chars max. */ int name_len; int mrows, ncols; /* text/data/map array dimensions */ int val_i; /* for misc use */ float val_f; /* for misc use */ double val_d; /* for misc use */ char *infile, *outfile, *maptitle, *basename; struct Cell_head region; void *raster, *ptr; RASTER_MAP_TYPE map_type; struct Option *inputfile, *outputfile; struct GModule *module; int fd; FILE *fp1; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("export")); module->description = _("Exports a GRASS raster to a binary MAT-File."); /* Define the different options */ inputfile = G_define_standard_option(G_OPT_R_INPUT); outputfile = G_define_option(); outputfile->key = "output"; outputfile->type = TYPE_STRING; outputfile->required = YES; outputfile->gisprompt = "new_file,file,output"; outputfile->description = _("Name for the output binary MAT-File"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); infile = inputfile->answer; basename = G_store(outputfile->answer); G_basename(basename, "mat"); outfile = G_malloc(strlen(basename) + 5); sprintf(outfile, "%s.mat", basename); fd = Rast_open_old(infile, ""); map_type = Rast_get_map_type(fd); /* open bin file for writing */ fp1 = fopen(outfile, "wb"); if (NULL == fp1) G_fatal_error(_("Unable to open output file <%s>"), outfile); /* Check Endian State of Host Computer */ if (G_is_little_endian()) endianness = 0; /* ie little endian */ else endianness = 1; /* ie big endian */ G_debug(1, "Machine is %s endian.\n", endianness ? "big" : "little"); G_get_window(®ion); /********** Write map **********/ /** write text element (map name) **/ strncpy(array_name, "map_name", 31); mrows = 1; ncols = strlen(infile); data_format = 5; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int(text) */ data_type = 1; /* 0=numbers 1=text */ G_verbose_message(_("Exporting <%s>"), infile); /* 4 byte data format */ format_block = endianness * 1000 + data_format * 10 + data_type; fwrite(&format_block, sizeof(int), 1, fp1); /* fprintf(stderr, "name data format is [%04ld]\n", format_block); */ /* 4 byte number of rows & columns */ fwrite(&mrows, sizeof(int), 1, fp1); fwrite(&ncols, sizeof(int), 1, fp1); /* 4 byte real/imag flag 0=real vals only */ fwrite(&realflag, sizeof(int), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(int), 1, fp1); /* array name */ fprintf(fp1, "%s%c", array_name, '\0'); /* array data */ fprintf(fp1, "%s", infile); /********** Write title (if there is one) **********/ maptitle = Rast_get_cell_title(infile, ""); if (strlen(maptitle) >= 1) { /** write text element (map title) **/ strncpy(array_name, "map_title", 31); mrows = 1; ncols = strlen(maptitle); data_format = 5; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int(text) */ data_type = 1; /* 0=numbers 1=text */ /* 4 byte data format */ format_block = endianness * 1000 + data_format * 10 + data_type; fwrite(&format_block, sizeof(int), 1, fp1); /* 4 byte number of rows & columns */ fwrite(&mrows, sizeof(int), 1, fp1); fwrite(&ncols, sizeof(int), 1, fp1); /* 4 byte real/imag flag 0=real vals only */ fwrite(&realflag, sizeof(int), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(int), 1, fp1); /* array name */ fprintf(fp1, "%s%c", array_name, '\0'); /* array data */ fprintf(fp1, "%s", maptitle); } /***** Write bounds *****/ G_verbose_message(""); G_verbose_message(_("Using the Current Region settings:")); G_verbose_message(_("northern edge=%f"), region.north); G_verbose_message(_("southern edge=%f"), region.south); G_verbose_message(_("eastern edge=%f"), region.east); G_verbose_message(_("western edge=%f"), region.west); G_verbose_message(_("nsres=%f"), region.ns_res); G_verbose_message(_("ewres=%f"), region.ew_res); G_verbose_message(_("rows=%d"), region.rows); G_verbose_message(_("cols=%d"), region.cols); G_verbose_message(""); for (i = 0; i < 4; i++) { switch (i) { case 0: strncpy(array_name, "map_northern_edge", 31); val_d = region.north; break; case 1: strncpy(array_name, "map_southern_edge", 31); val_d = region.south; break; case 2: strncpy(array_name, "map_eastern_edge", 31); val_d = region.east; break; case 3: strncpy(array_name, "map_western_edge", 31); val_d = region.west; break; default: fclose(fp1); G_fatal_error("please contact development team"); break; } /** write data element **/ data_format = 0; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int(text) */ data_type = 0; /* 0=numbers 1=text */ mrows = 1; ncols = 1; /* 4 byte data format */ format_block = endianness * 1000 + data_format * 10 + data_type; fwrite(&format_block, sizeof(int), 1, fp1); /* fprintf(stderr, "bounds data format is [%04ld]\n", format_block); */ /* 4 byte number of rows , 4 byte number of colums */ fwrite(&mrows, sizeof(int), 1, fp1); fwrite(&ncols, sizeof(int), 1, fp1); /* 4 byte real/imag flag 0=only real */ fwrite(&realflag, sizeof(int), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(int), 1, fp1); /* array name */ fprintf(fp1, "%s%c", array_name, '\0'); /* write array data, by increasing column */ fwrite(&val_d, sizeof(double), 1, fp1); /** end of data element **/ } /***** Write map data *****/ strncpy(array_name, "map_data", 31); switch (map_type) { /* data_format: 0=double 1=float 2=32bit signed int 5=8bit unsigned int (ie text) */ case CELL_TYPE: data_format = 2; G_verbose_message(_("Exporting raster as integer values")); break; case FCELL_TYPE: data_format = 1; G_verbose_message(_("Exporting raster as floating point values")); break; case DCELL_TYPE: data_format = 0; G_verbose_message(_("Exporting raster as double FP values")); break; default: fclose(fp1); G_fatal_error("Please contact development team"); break; } data_type = 0; /* 0=numbers 1=text */ mrows = region.rows; ncols = region.cols; /* 4 byte data format */ format_block = (endianness * 1000) + (data_format * 10) + data_type; fwrite(&format_block, sizeof(int), 1, fp1); G_debug(3, "map data format is [%04d]\n", format_block); /* 4 byte number of rows & columns */ fwrite(&mrows, sizeof(int), 1, fp1); fwrite(&ncols, sizeof(int), 1, fp1); /* 4 byte real/imag flag 0=only real */ fwrite(&realflag, sizeof(int), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(int), 1, fp1); /* array name */ fprintf(fp1, "%s%c", array_name, '\0'); /* data array, by increasing column */ raster = G_calloc((Rast_window_rows() + 1) * (Rast_window_cols() + 1), Rast_cell_size(map_type)); G_debug(1, "mem alloc is %d bytes\n", /* I think _cols()+1 is unneeded? */ Rast_cell_size(map_type) * (Rast_window_rows() + 1) * (Rast_window_cols() + 1)); G_verbose_message(_("Reading in map ... ")); /* load entire map into memory */ for (row = 0, ptr = raster; row < mrows; row++, ptr = G_incr_void_ptr(ptr, (Rast_window_cols() + 1) * Rast_cell_size(map_type))) { Rast_get_row(fd, ptr, row, map_type); G_percent(row, mrows, 2); } G_percent(row, mrows, 2); /* finish it off */ G_verbose_message(_("Writing out map...")); /* then write it to disk */ /* NoGood: fwrite(raster, Rast_cell_size(map_type), mrows*ncols, fp1); */ for (col = 0; col < ncols; col++) { for (row = 0; row < mrows; row++) { ptr = raster; ptr = G_incr_void_ptr(ptr, (col + row * (ncols + 1)) * Rast_cell_size(map_type)); if (!Rast_is_null_value(ptr, map_type)) { if (map_type == CELL_TYPE) { val_i = *((CELL *) ptr); fwrite(&val_i, sizeof(int), 1, fp1); } else if (map_type == FCELL_TYPE) { val_f = *((FCELL *) ptr); fwrite(&val_f, sizeof(float), 1, fp1); } else if (map_type == DCELL_TYPE) { val_d = *((DCELL *) ptr); fwrite(&val_d, sizeof(double), 1, fp1); } } else { /* ie if NULL cell -> write IEEE NaN value */ if (map_type == CELL_TYPE) { val_i = *((CELL *) ptr); /* int has no NaN value, so use whatever GRASS uses */ fwrite(&val_i, sizeof(int), 1, fp1); } else if (map_type == FCELL_TYPE) { if (endianness) /* ie big */ fprintf(fp1, "%c%c%c%c", 0xff, 0xf8, 0, 0); else /* ie little */ fprintf(fp1, "%c%c%c%c", 0, 0, 0xf8, 0xff); } else if (map_type == DCELL_TYPE) { if (endianness) fprintf(fp1, "%c%c%c%c%c%c%c%c", 0xff, 0xf8, 0, 0, 0, 0, 0, 0); else fprintf(fp1, "%c%c%c%c%c%c%c%c", 0, 0, 0, 0, 0, 0, 0xf8, 0xff); } } } G_percent(col, ncols, 2); } G_percent(col, ncols, 2); /* finish it off */ /*** end of data element ***/ /* done! */ filesize = G_ftell(fp1); fclose(fp1); G_verbose_message(_("%ld bytes written to '%s'"), filesize, outfile); G_done_msg(""); G_free(basename); G_free(outfile); exit(EXIT_SUCCESS); }
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; 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(); G_add_keyword(_("raster")); G_add_keyword(_("export")); module->description = _("Exports a GRASS raster to a binary array."); /* Define the different options */ parm.input = G_define_option(); parm.input->key = "input"; parm.input->type = TYPE_STRING; parm.input->required = YES; parm.input->gisprompt = "old,cell,raster"; parm.input->description = _("Name of input raster map"); parm.output = G_define_option(); parm.output->key = "output"; parm.output->type = TYPE_STRING; parm.output->required = NO; parm.output->description = _("Name for output binary map (use output=- for stdout)"); parm.null = G_define_option(); parm.null->key = "null"; 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 = _("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.swap = G_define_flag(); flag.swap->key = 's'; flag.swap->description = _("Byte swap output"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); 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) outfile = parm.output->answer; else { outfile = G_malloc(strlen(name) + 4 + 1); sprintf(outfile, "%s.bin", name); } 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; 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; } swap_flag = order == (G_is_little_endian() ? 0 : 1); do_stdout = strcmp("-", outfile) == 0; if (flag.int_out->answer && flag.float_out->answer) G_fatal_error(_("-i and -f are mutually exclusive")); fd = Rast_open_old(name, ""); if (flag.int_out->answer) is_fp = 0; else if (flag.float_out->answer) is_fp = 1; else is_fp = Rast_get_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(®ion); /* 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); /* Set up Parameters for GMT header */ if (flag.gmt_hd->answer) { if (!is_fp && bytes > 4) G_fatal_error(_("GMT grid doesn't support 64-bit integers")); make_gmt_header(&header, name, outfile, ®ion, null_val); } /* Write out BIL support files compatible with Arc-View */ if (flag.bil_hd->answer) { G_message(_("Creating BIL support files...")); write_bil_hdr(outfile, ®ion, bytes, order, flag.gmt_hd->answer, null_val); write_bil_wld(outfile, ®ion); } /* Write out GMT Header if required */ if (flag.gmt_hd->answer) write_gmt_header(&header, swap_flag, fp); nrows = Rast_window_rows(); ncols = Rast_window_cols(); in_buf = Rast_allocate_d_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 float format ID=1")); } else { G_message(_("Exporting raster as integer values (bytes=%d)"), bytes); if (flag.gmt_hd->answer) G_message(_("Writing GMT integer format ID=2")); } 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++) { G_percent(row, nrows, 2); Rast_get_d_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 */ Rast_close(fd); fclose(fp); return EXIT_SUCCESS; }