123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- /*
- * r.out.mat
- *
- * Output a GRASS raster map to a MAT-File (version 4).
- *
- * Copyright (C) 2004 by the GRASS Development Team
- * Author: Hamish Bowman, University of Otago, New Zealand
- *
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
- *
- * Code follows r.out.bin to a certain extent, which in turn
- * follows r.out.ascii.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/raster.h>
- #include <grass/glocale.h>
- 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_standard_option(G_OPT_F_OUTPUT);
- outputfile->required = YES;
- outputfile->gisprompt = "new,bin,file";
- outputfile->description = _("Name for 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 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');
- /* 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);
- }
|