main.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * r.out.mat
  3. *
  4. * Output a GRASS raster map to a MAT-File (version 4).
  5. *
  6. * Copyright (C) 2004 by the GRASS Development Team
  7. * Author: Hamish Bowman, University of Otago, New Zealand
  8. *
  9. * This program is free software under the GPL (>=v2)
  10. * Read the COPYING file that comes with GRASS for details.
  11. *
  12. * Code follows r.out.bin to a certain extent, which in turn
  13. * follows r.out.ascii.
  14. */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <grass/gis.h>
  19. #include <grass/raster.h>
  20. #include <grass/glocale.h>
  21. int main(int argc, char *argv[])
  22. {
  23. int i, row, col; /* counters */
  24. unsigned long filesize;
  25. int endianness; /* 0=little, 1=big */
  26. int data_format; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int (ie text) */
  27. int data_type; /* 0=numbers 1=text */
  28. int format_block; /* combo of endianness, 0, data_format, and type */
  29. int realflag = 0; /* 0=only real values used */
  30. /* should type be specifically uint32 ??? */
  31. char array_name[32]; /* variable names must start with a letter (case
  32. sensitive) followed by letters, numbers, or
  33. underscores. 31 chars max. */
  34. int name_len;
  35. int mrows, ncols; /* text/data/map array dimensions */
  36. int val_i; /* for misc use */
  37. float val_f; /* for misc use */
  38. double val_d; /* for misc use */
  39. char *infile, *outfile, *maptitle, *basename;
  40. struct Cell_head region;
  41. void *raster, *ptr;
  42. RASTER_MAP_TYPE map_type;
  43. struct Option *inputfile, *outputfile;
  44. struct GModule *module;
  45. int fd;
  46. FILE *fp1;
  47. G_gisinit(argv[0]);
  48. module = G_define_module();
  49. G_add_keyword(_("raster"));
  50. G_add_keyword(_("export"));
  51. module->description = _("Exports a GRASS raster to a binary MAT-File.");
  52. /* Define the different options */
  53. inputfile = G_define_standard_option(G_OPT_R_INPUT);
  54. outputfile = G_define_standard_option(G_OPT_F_OUTPUT);
  55. outputfile->required = YES;
  56. outputfile->gisprompt = "new,bin,file";
  57. outputfile->description = _("Name for output binary MAT file");
  58. if (G_parser(argc, argv))
  59. exit(EXIT_FAILURE);
  60. infile = inputfile->answer;
  61. basename = G_store(outputfile->answer);
  62. G_basename(basename, "mat");
  63. outfile = G_malloc(strlen(basename) + 5);
  64. sprintf(outfile, "%s.mat", basename);
  65. fd = Rast_open_old(infile, "");
  66. map_type = Rast_get_map_type(fd);
  67. /* open bin file for writing */
  68. fp1 = fopen(outfile, "wb");
  69. if (NULL == fp1)
  70. G_fatal_error(_("Unable to open output file <%s>"), outfile);
  71. /* Check Endian State of Host Computer */
  72. if (G_is_little_endian())
  73. endianness = 0; /* ie little endian */
  74. else
  75. endianness = 1; /* ie big endian */
  76. G_debug(1, "Machine is %s endian.\n", endianness ? "big" : "little");
  77. G_get_window(&region);
  78. /********** Write map **********/
  79. /** write text element (map name) **/
  80. strncpy(array_name, "map_name", 31);
  81. mrows = 1;
  82. ncols = strlen(infile);
  83. data_format = 5; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int(text) */
  84. data_type = 1; /* 0=numbers 1=text */
  85. G_verbose_message(_("Exporting <%s>"), infile);
  86. /* 4 byte data format */
  87. format_block = endianness * 1000 + data_format * 10 + data_type;
  88. fwrite(&format_block, sizeof(int), 1, fp1);
  89. /* fprintf(stderr, "name data format is [%04ld]\n", format_block); */
  90. /* 4 byte number of rows & columns */
  91. fwrite(&mrows, sizeof(int), 1, fp1);
  92. fwrite(&ncols, sizeof(int), 1, fp1);
  93. /* 4 byte real/imag flag 0=real vals only */
  94. fwrite(&realflag, sizeof(int), 1, fp1);
  95. /* length of array_name+1 */
  96. name_len = strlen(array_name) + 1;
  97. fwrite(&name_len, sizeof(int), 1, fp1);
  98. /* array name */
  99. fprintf(fp1, "%s%c", array_name, '\0');
  100. /* array data */
  101. fprintf(fp1, "%s", infile);
  102. /********** Write title (if there is one) **********/
  103. maptitle = Rast_get_cell_title(infile, "");
  104. if (strlen(maptitle) >= 1) {
  105. /** write text element (map title) **/
  106. strncpy(array_name, "map_title", 31);
  107. mrows = 1;
  108. ncols = strlen(maptitle);
  109. data_format = 5; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int(text) */
  110. data_type = 1; /* 0=numbers 1=text */
  111. /* 4 byte data format */
  112. format_block = endianness * 1000 + data_format * 10 + data_type;
  113. fwrite(&format_block, sizeof(int), 1, fp1);
  114. /* 4 byte number of rows & columns */
  115. fwrite(&mrows, sizeof(int), 1, fp1);
  116. fwrite(&ncols, sizeof(int), 1, fp1);
  117. /* 4 byte real/imag flag 0=real vals only */
  118. fwrite(&realflag, sizeof(int), 1, fp1);
  119. /* length of array_name+1 */
  120. name_len = strlen(array_name) + 1;
  121. fwrite(&name_len, sizeof(int), 1, fp1);
  122. /* array name */
  123. fprintf(fp1, "%s%c", array_name, '\0');
  124. /* array data */
  125. fprintf(fp1, "%s", maptitle);
  126. }
  127. /***** Write bounds *****/
  128. G_verbose_message("");
  129. G_verbose_message(_("Using the Current Region settings:"));
  130. G_verbose_message(_("northern edge=%f"), region.north);
  131. G_verbose_message(_("southern edge=%f"), region.south);
  132. G_verbose_message(_("eastern edge=%f"), region.east);
  133. G_verbose_message(_("western edge=%f"), region.west);
  134. G_verbose_message(_("nsres=%f"), region.ns_res);
  135. G_verbose_message(_("ewres=%f"), region.ew_res);
  136. G_verbose_message(_("rows=%d"), region.rows);
  137. G_verbose_message(_("cols=%d"), region.cols);
  138. G_verbose_message("");
  139. for (i = 0; i < 4; i++) {
  140. switch (i) {
  141. case 0:
  142. strncpy(array_name, "map_northern_edge", 31);
  143. val_d = region.north;
  144. break;
  145. case 1:
  146. strncpy(array_name, "map_southern_edge", 31);
  147. val_d = region.south;
  148. break;
  149. case 2:
  150. strncpy(array_name, "map_eastern_edge", 31);
  151. val_d = region.east;
  152. break;
  153. case 3:
  154. strncpy(array_name, "map_western_edge", 31);
  155. val_d = region.west;
  156. break;
  157. default:
  158. fclose(fp1);
  159. G_fatal_error("please contact development team");
  160. break;
  161. }
  162. /** write data element **/
  163. data_format = 0; /* 0=double 1=float 2=32bit signed int 5=8bit unsigned int(text) */
  164. data_type = 0; /* 0=numbers 1=text */
  165. mrows = 1;
  166. ncols = 1;
  167. /* 4 byte data format */
  168. format_block = endianness * 1000 + data_format * 10 + data_type;
  169. fwrite(&format_block, sizeof(int), 1, fp1);
  170. /* fprintf(stderr, "bounds data format is [%04ld]\n", format_block); */
  171. /* 4 byte number of rows , 4 byte number of columns */
  172. fwrite(&mrows, sizeof(int), 1, fp1);
  173. fwrite(&ncols, sizeof(int), 1, fp1);
  174. /* 4 byte real/imag flag 0=only real */
  175. fwrite(&realflag, sizeof(int), 1, fp1);
  176. /* length of array_name+1 */
  177. name_len = strlen(array_name) + 1;
  178. fwrite(&name_len, sizeof(int), 1, fp1);
  179. /* array name */
  180. fprintf(fp1, "%s%c", array_name, '\0');
  181. /* write array data, by increasing column */
  182. fwrite(&val_d, sizeof(double), 1, fp1);
  183. /** end of data element **/
  184. }
  185. /***** Write map data *****/
  186. strncpy(array_name, "map_data", 31);
  187. switch (map_type) { /* data_format: 0=double 1=float 2=32bit signed int 5=8bit unsigned int (ie text) */
  188. case CELL_TYPE:
  189. data_format = 2;
  190. G_verbose_message(_("Exporting raster as integer values"));
  191. break;
  192. case FCELL_TYPE:
  193. data_format = 1;
  194. G_verbose_message(_("Exporting raster as floating point values"));
  195. break;
  196. case DCELL_TYPE:
  197. data_format = 0;
  198. G_verbose_message(_("Exporting raster as double FP values"));
  199. break;
  200. default:
  201. fclose(fp1);
  202. G_fatal_error("Please contact development team");
  203. break;
  204. }
  205. data_type = 0; /* 0=numbers 1=text */
  206. mrows = region.rows;
  207. ncols = region.cols;
  208. /* 4 byte data format */
  209. format_block = (endianness * 1000) + (data_format * 10) + data_type;
  210. fwrite(&format_block, sizeof(int), 1, fp1);
  211. G_debug(3, "map data format is [%04d]\n", format_block);
  212. /* 4 byte number of rows & columns */
  213. fwrite(&mrows, sizeof(int), 1, fp1);
  214. fwrite(&ncols, sizeof(int), 1, fp1);
  215. /* 4 byte real/imag flag 0=only real */
  216. fwrite(&realflag, sizeof(int), 1, fp1);
  217. /* length of array_name+1 */
  218. name_len = strlen(array_name) + 1;
  219. fwrite(&name_len, sizeof(int), 1, fp1);
  220. /* array name */
  221. fprintf(fp1, "%s%c", array_name, '\0');
  222. /* data array, by increasing column */
  223. raster =
  224. G_calloc((Rast_window_rows() + 1) * (Rast_window_cols() + 1),
  225. Rast_cell_size(map_type));
  226. G_debug(1, "mem alloc is %d bytes\n", /* I think _cols()+1 is unneeded? */
  227. Rast_cell_size(map_type) * (Rast_window_rows() +
  228. 1) * (Rast_window_cols() + 1));
  229. G_verbose_message(_("Reading in map ... "));
  230. /* load entire map into memory */
  231. for (row = 0, ptr = raster; row < mrows; row++,
  232. ptr =
  233. G_incr_void_ptr(ptr,
  234. (Rast_window_cols() + 1) * Rast_cell_size(map_type))) {
  235. Rast_get_row(fd, ptr, row, map_type);
  236. G_percent(row, mrows, 2);
  237. }
  238. G_percent(row, mrows, 2); /* finish it off */
  239. G_verbose_message(_("Writing out map..."));
  240. /* then write it to disk */
  241. /* NoGood: fwrite(raster, Rast_cell_size(map_type), mrows*ncols, fp1); */
  242. for (col = 0; col < ncols; col++) {
  243. for (row = 0; row < mrows; row++) {
  244. ptr = raster;
  245. ptr =
  246. G_incr_void_ptr(ptr,
  247. (col +
  248. row * (ncols +
  249. 1)) * Rast_cell_size(map_type));
  250. if (!Rast_is_null_value(ptr, map_type)) {
  251. if (map_type == CELL_TYPE) {
  252. val_i = *((CELL *) ptr);
  253. fwrite(&val_i, sizeof(int), 1, fp1);
  254. }
  255. else if (map_type == FCELL_TYPE) {
  256. val_f = *((FCELL *) ptr);
  257. fwrite(&val_f, sizeof(float), 1, fp1);
  258. }
  259. else if (map_type == DCELL_TYPE) {
  260. val_d = *((DCELL *) ptr);
  261. fwrite(&val_d, sizeof(double), 1, fp1);
  262. }
  263. }
  264. else { /* ie if NULL cell -> write IEEE NaN value */
  265. if (map_type == CELL_TYPE) {
  266. val_i = *((CELL *) ptr); /* int has no NaN value, so use whatever GRASS uses */
  267. fwrite(&val_i, sizeof(int), 1, fp1);
  268. }
  269. else if (map_type == FCELL_TYPE) {
  270. if (endianness) /* ie big */
  271. fprintf(fp1, "%c%c%c%c", 0xff, 0xf8, 0, 0);
  272. else /* ie little */
  273. fprintf(fp1, "%c%c%c%c", 0, 0, 0xf8, 0xff);
  274. }
  275. else if (map_type == DCELL_TYPE) {
  276. if (endianness)
  277. fprintf(fp1, "%c%c%c%c%c%c%c%c", 0xff, 0xf8, 0, 0, 0,
  278. 0, 0, 0);
  279. else
  280. fprintf(fp1, "%c%c%c%c%c%c%c%c", 0, 0, 0, 0, 0, 0,
  281. 0xf8, 0xff);
  282. }
  283. }
  284. }
  285. G_percent(col, ncols, 2);
  286. }
  287. G_percent(col, ncols, 2); /* finish it off */
  288. /*** end of data element ***/
  289. /* done! */
  290. filesize = G_ftell(fp1);
  291. fclose(fp1);
  292. G_verbose_message(_("%ld bytes written to '%s'"), filesize, outfile);
  293. G_done_msg("");
  294. G_free(basename);
  295. G_free(outfile);
  296. exit(EXIT_SUCCESS);
  297. }