main.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /****************************************************************************
  2. *
  3. * MODULE: r.tile
  4. * AUTHOR(S): Glynn Clements <glynn gclements.plus.com>
  5. * PURPOSE: Retiles an existing raster map with user defined x and y tile size
  6. * COPYRIGHT: (C) 2013 by Glynn Clements and the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public
  9. * License (>=v2). Read the file COPYING that comes with GRASS
  10. * for details.
  11. *
  12. *****************************************************************************/
  13. #include <stdlib.h>
  14. #include <grass/gis.h>
  15. #include <grass/raster.h>
  16. #include <grass/glocale.h>
  17. static struct
  18. {
  19. struct Option *rastin, *rastout, *width, *height, *overlap;
  20. } parm;
  21. static struct Cell_head dst_w, src_w, ovl_w;
  22. static int xtiles, ytiles;
  23. static RASTER_MAP_TYPE map_type;
  24. static void write_support_files(int xtile, int ytile, int overlap);
  25. int main(int argc, char *argv[])
  26. {
  27. struct GModule *module;
  28. int infile;
  29. const char *mapset;
  30. size_t cell_size;
  31. int ytile, xtile, y, overlap;
  32. int *outfiles;
  33. void *inbuf;
  34. G_gisinit(argv[0]);
  35. module = G_define_module();
  36. G_add_keyword(_("raster"));
  37. G_add_keyword(_("tiling"));
  38. module->description =
  39. _("Splits a raster map into tiles.");
  40. parm.rastin = G_define_standard_option(G_OPT_R_INPUT);
  41. parm.rastout = G_define_option();
  42. parm.rastout->key = "output";
  43. parm.rastout->type = TYPE_STRING;
  44. parm.rastout->required = YES;
  45. parm.rastout->multiple = NO;
  46. parm.rastout->description = _("Output base name");
  47. parm.width = G_define_option();
  48. parm.width->key = "width";
  49. parm.width->type = TYPE_INTEGER;
  50. parm.width->required = YES;
  51. parm.width->multiple = NO;
  52. parm.width->description = _("Width of tiles (columns)");
  53. parm.height = G_define_option();
  54. parm.height->key = "height";
  55. parm.height->type = TYPE_INTEGER;
  56. parm.height->required = YES;
  57. parm.height->multiple = NO;
  58. parm.height->description = _("Height of tiles (rows)");
  59. parm.overlap = G_define_option();
  60. parm.overlap->key = "overlap";
  61. parm.overlap->type = TYPE_INTEGER;
  62. parm.overlap->required = NO;
  63. parm.overlap->multiple = NO;
  64. parm.overlap->description = _("Overlap of tiles");
  65. if (G_parser(argc, argv))
  66. exit(EXIT_FAILURE);
  67. G_get_set_window(&src_w);
  68. overlap = parm.overlap->answer ? atoi(parm.overlap->answer) : 0;
  69. mapset = G_find_raster2(parm.rastin->answer, "");
  70. if (mapset == NULL)
  71. G_fatal_error(_("Raster map <%s> not found"), parm.rastin->answer);
  72. /* set window to old map */
  73. Rast_get_cellhd(parm.rastin->answer, "", &src_w);
  74. dst_w = src_w;
  75. dst_w.cols = atoi(parm.width->answer);
  76. dst_w.rows = atoi(parm.height->answer);
  77. G_adjust_Cell_head(&dst_w, 1, 1);
  78. xtiles = (src_w.cols + dst_w.cols - 1) / dst_w.cols;
  79. ytiles = (src_w.rows + dst_w.rows - 1) / dst_w.rows;
  80. G_debug(1, "X: %d * %d, Y: %d * %d",
  81. xtiles, dst_w.cols, ytiles, dst_w.rows);
  82. src_w.cols = xtiles * dst_w.cols + 2 * overlap;
  83. src_w.rows = ytiles * dst_w.rows + 2 * overlap;
  84. src_w.west = src_w.west - overlap * src_w.ew_res;
  85. src_w.east = src_w.west + (src_w.cols + 2 * overlap) * src_w.ew_res;
  86. src_w.north = src_w.north + overlap * src_w.ns_res;
  87. src_w.south = src_w.north - (src_w.rows + 2 * overlap) * src_w.ns_res;
  88. Rast_set_input_window(&src_w);
  89. /* set the output region */
  90. ovl_w = dst_w;
  91. ovl_w.cols = ovl_w.cols + 2 * overlap;
  92. ovl_w.rows = ovl_w.rows + 2 * overlap;
  93. G_adjust_Cell_head(&ovl_w, 1, 1);
  94. Rast_set_output_window(&ovl_w);
  95. infile = Rast_open_old(parm.rastin->answer, "");
  96. map_type = Rast_get_map_type(infile);
  97. cell_size = Rast_cell_size(map_type);
  98. inbuf = Rast_allocate_input_buf(map_type);
  99. outfiles = G_malloc(xtiles * sizeof(int));
  100. G_debug(1, "X: %d * %d, Y: %d * %d",
  101. xtiles, dst_w.cols, ytiles, dst_w.rows);
  102. G_message(_("Generating %d x %d = %d tiles..."), xtiles, ytiles, xtiles * ytiles);
  103. for (ytile = 0; ytile < ytiles; ytile++) {
  104. G_debug(1, "reading y tile: %d", ytile);
  105. G_percent(ytile, ytiles, 2);
  106. for (xtile = 0; xtile < xtiles; xtile++) {
  107. char name[GNAME_MAX];
  108. sprintf(name, "%s-%03d-%03d", parm.rastout->answer, ytile, xtile);
  109. outfiles[xtile] = Rast_open_new(name, map_type);
  110. }
  111. for (y = 0; y < ovl_w.rows; y++) {
  112. int row = ytile * dst_w.rows + y;
  113. G_debug(1, "reading row: %d", row);
  114. Rast_get_row(infile, inbuf, row, map_type);
  115. for (xtile = 0; xtile < xtiles; xtile++) {
  116. int cells = xtile * dst_w.cols;
  117. void *ptr = G_incr_void_ptr(inbuf, cells * cell_size);
  118. Rast_put_row(outfiles[xtile], ptr, map_type);
  119. }
  120. }
  121. for (xtile = 0; xtile < xtiles; xtile++) {
  122. Rast_close(outfiles[xtile]);
  123. write_support_files(xtile, ytile, overlap);
  124. }
  125. }
  126. Rast_close(infile);
  127. return EXIT_SUCCESS;
  128. }
  129. static void write_support_files(int xtile, int ytile, int overlap)
  130. {
  131. char name[GNAME_MAX];
  132. struct Cell_head cellhd;
  133. char title[64];
  134. struct History history;
  135. struct Colors colors;
  136. struct Categories cats;
  137. sprintf(name, "%s-%03d-%03d", parm.rastout->answer, ytile, xtile);
  138. Rast_get_cellhd(name, G_mapset(), &cellhd);
  139. cellhd.north = src_w.north - ytile * dst_w.rows * src_w.ns_res;
  140. cellhd.south = cellhd.north - (dst_w.rows + 2 * overlap) * src_w.ns_res;
  141. cellhd.west = src_w.west + xtile * dst_w.cols * src_w.ew_res;
  142. cellhd.east = cellhd.west + (dst_w.cols + 2 * overlap) * src_w.ew_res;
  143. Rast_put_cellhd(name, &cellhd);
  144. /* copy cats from source map */
  145. if (Rast_read_cats(parm.rastin->answer, "", &cats) < 0)
  146. G_fatal_error(_("Unable to read cats for %s"),
  147. parm.rastin->answer);
  148. Rast_write_cats(name, &cats);
  149. /* record map metadata/history info */
  150. G_debug(1, "Tile %d,%d of %s: writing %s", xtile, ytile, parm.rastin->answer, name);
  151. sprintf(title, "Tile %d,%d of %s", xtile, ytile, parm.rastin->answer);
  152. Rast_put_cell_title(name, title);
  153. Rast_short_history(name, "raster", &history);
  154. Rast_set_history(&history, HIST_DATSRC_1, parm.rastin->answer);
  155. Rast_command_history(&history);
  156. Rast_write_history(name, &history);
  157. /* copy color table from source map */
  158. if (Rast_read_colors(parm.rastin->answer, "", &colors) < 0)
  159. G_fatal_error(_("Unable to read color table for %s"),
  160. parm.rastin->answer);
  161. if (map_type != CELL_TYPE)
  162. Rast_mark_colors_as_fp(&colors);
  163. Rast_write_colors(name, G_mapset(), &colors);
  164. }