main.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /****************************************************************************
  2. *
  3. * MODULE: r3.out.bin
  4. *
  5. * AUTHOR(S): Soeren Gebbert
  6. * Based on r.out.bin from: Bob Covill and Glynn Clements
  7. *
  8. * PURPOSE: Exports a GRASS 3D raster map to a binary array.
  9. *
  10. * COPYRIGHT: (C) 2012 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. *****************************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <grass/gis.h>
  21. #include <grass/raster.h>
  22. #include <grass/raster3d.h>
  23. #include <grass/glocale.h>
  24. RASTER3D_Map *map;
  25. RASTER3D_Region region;
  26. unsigned char *out_cell;
  27. static void swap_2(void *p) {
  28. unsigned char *q = p;
  29. unsigned char t;
  30. t = q[0];
  31. q[0] = q[1];
  32. q[1] = t;
  33. }
  34. static void swap_4(void *p) {
  35. unsigned char *q = p;
  36. unsigned char t;
  37. t = q[0];
  38. q[0] = q[3];
  39. q[3] = t;
  40. t = q[1];
  41. q[1] = q[2];
  42. q[2] = t;
  43. }
  44. static void swap_8(void *p) {
  45. unsigned char *q = p;
  46. unsigned char t;
  47. t = q[0];
  48. q[0] = q[7];
  49. q[7] = t;
  50. t = q[1];
  51. q[1] = q[6];
  52. q[6] = t;
  53. t = q[2];
  54. q[2] = q[5];
  55. q[5] = t;
  56. t = q[3];
  57. q[3] = q[4];
  58. q[4] = t;
  59. }
  60. static void write_cell(FILE *fp, const DCELL in_cell, int as_integer, int bytes,
  61. int swap_flag) {
  62. if (!as_integer) {
  63. switch (bytes) {
  64. case 4:
  65. *(float *) out_cell = (float) in_cell;
  66. break;
  67. case 8:
  68. *(double *) out_cell = (double) in_cell;
  69. break;
  70. }
  71. } else {
  72. switch (bytes) {
  73. case 1:
  74. *(unsigned char *) out_cell = (unsigned char) in_cell;
  75. break;
  76. case 2:
  77. *(short *) out_cell = (short) in_cell;
  78. break;
  79. case 4:
  80. *(int *) out_cell = (int) in_cell;
  81. break;
  82. #ifdef HAVE_LONG_LONG_INT
  83. case 8:
  84. *(long long *) out_cell = (long long) in_cell;
  85. break;
  86. #endif
  87. }
  88. }
  89. if (swap_flag) {
  90. switch (bytes) {
  91. case 1:
  92. break;
  93. case 2:
  94. swap_2(out_cell);
  95. break;
  96. case 4:
  97. swap_4(out_cell);
  98. break;
  99. case 8:
  100. swap_8(out_cell);
  101. break;
  102. }
  103. }
  104. if (fwrite(out_cell, bytes, 1, fp) != 1)
  105. G_fatal_error(_("Error writing data"));
  106. }
  107. static void raster3d_to_bin(FILE * fp, DCELL null_value, int as_integer,
  108. int bytes, int byte_swap, int row_swap, int depth_swap) {
  109. DCELL dvalue;
  110. FCELL fvalue;
  111. int x, y, z;
  112. int rows, cols, depths, typeIntern;
  113. int col, row, depth;
  114. rows = region.rows;
  115. cols = region.cols;
  116. depths = region.depths;
  117. typeIntern = Rast3d_tile_type_map(map);
  118. for (z = 0; z < depths; z++) {
  119. G_percent(z, depths, 1);
  120. for (y = 0; y < rows; y++) {
  121. for (x = 0; x < cols; x++) {
  122. /* From west to east */
  123. col = x;
  124. /* The default is to write rows from north to south
  125. */
  126. row = y;
  127. /* From bottom to the top */
  128. depth = z;
  129. /* Write rows from south to north */
  130. if (row_swap)
  131. row = rows - y - 1;
  132. /* write XY layer from top to bottom */
  133. if (depth_swap)
  134. depth = depths - z - 1;
  135. if (typeIntern == FCELL_TYPE) {
  136. Rast3d_get_value(map, col, row, depth, &fvalue, FCELL_TYPE);
  137. if (Rast3d_is_null_value_num(&fvalue, FCELL_TYPE))
  138. write_cell(fp, null_value, as_integer, bytes,
  139. byte_swap);
  140. else
  141. write_cell(fp, (DCELL) fvalue, as_integer, bytes,
  142. byte_swap);
  143. } else {
  144. Rast3d_get_value(map, col, row, depth, &dvalue, DCELL_TYPE);
  145. if (Rast3d_is_null_value_num(&dvalue, DCELL_TYPE))
  146. write_cell(fp, null_value, as_integer, bytes,
  147. byte_swap);
  148. else
  149. write_cell(fp, dvalue, as_integer, bytes, byte_swap);
  150. }
  151. }
  152. }
  153. }
  154. G_percent(1, 1, 1);
  155. G_percent_reset();
  156. }
  157. int main(int argc, char *argv[]) {
  158. struct GModule *module;
  159. struct {
  160. struct Option *input;
  161. struct Option *output;
  162. struct Option *null;
  163. struct Option *order;
  164. struct Option *bytes;
  165. } parm;
  166. struct {
  167. struct Flag *swap, *row, *depth, *integer;
  168. } flag;
  169. char *name;
  170. char *outfile;
  171. double null_val;
  172. int do_stdout;
  173. int order;
  174. int swap_flag;
  175. int bytes;
  176. int as_integer = 0;
  177. FILE *fp;
  178. out_cell = NULL;
  179. G_gisinit(argv[0]);
  180. module = G_define_module();
  181. G_add_keyword(_("raster3d"));
  182. G_add_keyword(_("export"));
  183. module->description = _("Exports a GRASS 3D raster map to a binary array.");
  184. /* Define the different options */
  185. parm.input = G_define_standard_option(G_OPT_R3_INPUT);
  186. parm.output = G_define_standard_option(G_OPT_F_OUTPUT);
  187. parm.null = G_define_option();
  188. parm.null->key = "null";
  189. parm.null->type = TYPE_DOUBLE;
  190. parm.null->required = NO;
  191. parm.null->answer = "0";
  192. parm.null->description = _("Value to write out for null");
  193. parm.bytes = G_define_option();
  194. parm.bytes->key = "bytes";
  195. parm.bytes->type = TYPE_INTEGER;
  196. parm.bytes->required = YES;
  197. parm.bytes->options = "1,2,4,8";
  198. parm.bytes->description = _("Number of bytes per cell in binary file");
  199. parm.bytes->guisection = _("Settings");
  200. parm.order = G_define_option();
  201. parm.order->key = "order";
  202. parm.order->type = TYPE_STRING;
  203. parm.order->required = NO;
  204. parm.order->options = "big,little,native,swap";
  205. parm.order->description = _("Output byte order");
  206. parm.order->answer = "native";
  207. flag.swap = G_define_flag();
  208. flag.swap->key = 's';
  209. flag.swap->description = _("Byte swap output");
  210. flag.row = G_define_flag();
  211. flag.row->key = 'r';
  212. flag.row->description = _("Switch the row order in output from "
  213. "north->south to south->north");
  214. flag.depth = G_define_flag();
  215. flag.depth->key = 'd';
  216. flag.depth->description = _("Switch the depth order in output "
  217. "from bottom->top to top->bottom");
  218. flag.integer = G_define_flag();
  219. flag.integer->key = 'i';
  220. flag.integer->description = _("Write data as integer");
  221. if (G_parser(argc, argv))
  222. exit(EXIT_FAILURE);
  223. if (sscanf(parm.null->answer, "%lf", &null_val) != 1)
  224. G_fatal_error(_("Invalid value for null (integers only)"));
  225. as_integer = flag.integer->answer;
  226. name = parm.input->answer;
  227. if (parm.bytes->answer)
  228. bytes = atoi(parm.bytes->answer);
  229. else if (as_integer)
  230. bytes = 4;
  231. else
  232. bytes = 8;
  233. if (!as_integer && bytes < 4)
  234. G_fatal_error(_("Floating-point output requires bytes=4 or bytes=8"));
  235. #ifndef HAVE_LONG_LONG_INT
  236. if (as_integer && bytes > 4)
  237. G_fatal_error(_("Integer output doesn't support bytes=8 in this build"));
  238. #endif
  239. if (parm.output->answer)
  240. outfile = parm.output->answer;
  241. else {
  242. outfile = G_malloc(strlen(name) + 4 + 1);
  243. G_snprintf(outfile, sizeof(outfile), "%s.bin", name);
  244. }
  245. if (G_strcasecmp(parm.order->answer, "big") == 0)
  246. order = 0;
  247. else if (G_strcasecmp(parm.order->answer, "little") == 0)
  248. order = 1;
  249. else if (G_strcasecmp(parm.order->answer, "native") == 0)
  250. order = G_is_little_endian() ? 1 : 0;
  251. else if (G_strcasecmp(parm.order->answer, "swap") == 0)
  252. order = G_is_little_endian() ? 0 : 1;
  253. if (flag.swap->answer) {
  254. if (strcmp(parm.order->answer, "native") != 0)
  255. G_fatal_error(_("order= and -s are mutually exclusive"));
  256. order = G_is_little_endian() ? 0 : 1;
  257. }
  258. swap_flag = order == (G_is_little_endian() ? 0 : 1);
  259. do_stdout = strcmp("-", outfile) == 0;
  260. out_cell = G_malloc(bytes);
  261. if (NULL == G_find_raster3d(parm.input->answer, ""))
  262. Rast3d_fatal_error(_("3D raster map <%s> not found"),
  263. parm.input->answer);
  264. /* Initiate the default settings */
  265. Rast3d_init_defaults();
  266. /* Figure out the current region settings */
  267. Rast3d_get_window(&region);
  268. /* Open the map and use XY cache mode */
  269. map = Rast3d_open_cell_old(parm.input->answer,
  270. G_find_raster3d(parm.input->answer, ""), &region,
  271. RASTER3D_TILE_SAME_AS_FILE, RASTER3D_USE_CACHE_DEFAULT);
  272. if (map == NULL)
  273. Rast3d_fatal_error(_("Error opening 3d raster map <%s>"),
  274. parm.input->answer);
  275. /* open bin file for writing */
  276. if (do_stdout)
  277. fp = stdout;
  278. else if (NULL == (fp = fopen(outfile, "w")))
  279. G_fatal_error(_("Unable to create file <%s>"), outfile);
  280. G_verbose_message(_("Using the current region settings..."));
  281. G_verbose_message(_("north=%f"), region.north);
  282. G_verbose_message(_("south=%f"), region.south);
  283. G_verbose_message(_("east=%f"), region.east);
  284. G_verbose_message(_("west=%f"), region.west);
  285. G_verbose_message(_("top=%f"), region.top);
  286. G_verbose_message(_("bottom=%f"), region.bottom);
  287. G_verbose_message(_("rows=%d"), region.rows);
  288. G_verbose_message(_("cols=%d"), region.cols);
  289. G_verbose_message(_("depths=%d"), region.depths);
  290. raster3d_to_bin(fp, null_val, as_integer, bytes, swap_flag,
  291. flag.row->answer, flag.depth->answer);
  292. Rast3d_close(map);
  293. fclose(fp);
  294. if(out_cell)
  295. G_free(out_cell);
  296. return EXIT_SUCCESS;
  297. }