/* * r.out.mat * * Output a GRASS raster file 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 #include #include #include #include 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 */ long format_block; /* combo of endianness, 0, data_format, and type */ long 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; long 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, *mapset, *maptitle; struct Cell_head region; void *raster, *ptr; RASTER_MAP_TYPE map_type; struct Option *inputfile, *outputfile; struct Flag *verbose; struct GModule *module; int fd; FILE *fp1; G_gisinit(argv[0]); module = G_define_module(); module->keywords = _("raster"); module->description = _("Exports a GRASS raster to a binary MAT-File."); /* Define the different options */ inputfile = G_define_option() ; inputfile->key = "input"; inputfile->type = TYPE_STRING; inputfile->required = YES; inputfile->gisprompt = "old,cell,raster" ; inputfile->description= _("Name of an existing raster map") ; outputfile = G_define_option() ; outputfile->key = "output"; outputfile->type = TYPE_STRING; outputfile->required = YES; outputfile->description= _("Name for the output binary MAT-File") ; verbose = G_define_flag(); verbose->key = 'v'; verbose->description = _("Verbose mode"); if (G_parser(argc,argv)) exit(1); infile = inputfile->answer; outfile = outputfile->answer; mapset = G_find_cell2 (infile, ""); if (mapset == NULL) { G_fatal_error(_("raster <%s> not found"), infile); } map_type = G_raster_map_type(infile, mapset); fd = G_open_cell_old (infile, mapset); if (fd < 0) G_fatal_error(_("unable to open <%s>"), infile); /* 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 */ fprintf(stderr, "Exporting <%s>\n", infile); /* 4 byte data format */ format_block = endianness*1000 + data_format*10 + data_type; fwrite(&format_block, sizeof(long), 1, fp1); /* fprintf(stderr, "name data format is [%04ld]\n", format_block); */ /* 4 byte number of rows & columns */ fwrite(&mrows, sizeof(long), 1, fp1); fwrite(&ncols, sizeof(long), 1, fp1); /* 4 byte real/imag flag 0=real vals only */ fwrite(&realflag, sizeof(long), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(long), 1, fp1); /* array name */ fprintf(fp1, "%s%c", array_name, '\0'); /* array data */ fprintf(fp1, "%s", infile); /********** Write title (if there is one) **********/ maptitle = G_get_cell_title (infile, mapset); 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(long), 1, fp1); /* 4 byte number of rows & columns */ fwrite(&mrows, sizeof(long), 1, fp1); fwrite(&ncols, sizeof(long), 1, fp1); /* 4 byte real/imag flag 0=real vals only */ fwrite(&realflag, sizeof(long), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(long), 1, fp1); /* array name */ fprintf(fp1, "%s%c", array_name, '\0'); /* array data */ fprintf(fp1, "%s", maptitle); } /***** Write bounds *****/ if(verbose->answer) { fprintf(stderr, "\nUsing the Current Region settings:\n"); fprintf(stderr, "northern edge=%f\n", region.north); fprintf(stderr, "southern edge=%f\n", region.south); fprintf(stderr, "eastern edge=%f\n", region.east); fprintf(stderr, "western edge=%f\n", region.west); fprintf(stderr, "nsres=%f\n", region.ns_res); fprintf(stderr, "ewres=%f\n", region.ew_res); fprintf(stderr, "rows=%d\n", region.rows); fprintf(stderr, "cols=%d\n\n", region.cols); } 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(long), 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(long), 1, fp1); fwrite(&ncols, sizeof(long), 1, fp1); /* 4 byte real/imag flag 0=only real */ fwrite(&realflag, sizeof(long), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(long), 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; if(verbose->answer) fprintf(stderr, "Exporting raster as integer values\n\n"); break; case FCELL_TYPE: data_format = 1; if(verbose->answer) fprintf(stderr, "Exporting raster as floating point values\n\n"); break; case DCELL_TYPE: data_format = 0; if(verbose->answer) fprintf(stderr, "Exporting raster as double FP values\n\n"); 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(long), 1, fp1); G_debug(3, "map data format is [%04ld]\n", format_block); /* 4 byte number of rows & columns*/ fwrite(&mrows, sizeof(long), 1, fp1); fwrite(&ncols, sizeof(long), 1, fp1); /* 4 byte real/imag flag 0=only real */ fwrite(&realflag, sizeof(long), 1, fp1); /* length of array_name+1 */ name_len = strlen(array_name) + 1; fwrite(&name_len, sizeof(long), 1, fp1); /* array name */ fprintf(fp1, "%s%c", array_name, '\0'); /* data array, by increasing column */ raster = G_calloc ((G_window_rows()+1)*(G_window_cols()+1), G_raster_size(map_type)); G_debug(1, "mem alloc is %d bytes\n", /* I think _cols()+1 is unneeded? */ G_raster_size(map_type)*(G_window_rows()+1)*(G_window_cols()+1) ); fprintf(stderr, "Reading in map .. "); fflush(stderr); /* load entire map into memory */ for (row = 0, ptr = raster; row < mrows; row++, ptr = G_incr_void_ptr(ptr, (G_window_cols()+1)*G_raster_size(map_type))) { if (G_get_raster_row(fd, ptr, row, map_type) < 0) G_fatal_error("reading map"); G_percent(row, mrows, 2); } G_percent(row, mrows, 2); /* finish it off */ fprintf(stderr, "Writing out map .. "); fflush(stderr); /* then write it to disk */ /* NoGood: fwrite(raster, G_raster_size(map_type), mrows*ncols, fp1); */ for(col=0; col 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=ftell(fp1); fclose(fp1); if(verbose->answer) fprintf(stderr, "\n%ld bytes written to '%s'.\n", filesize, outfile); G_done_msg(""); return 0; }