main.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /****************************************************************************
  2. *
  3. * MODULE: r.external.out
  4. *
  5. * AUTHOR(S): Glynn Clements, based on r.out.gdal
  6. *
  7. * PURPOSE: Make GRASS write raster maps utilizing the GDAL library.
  8. *
  9. * COPYRIGHT: (C) 2008, 2010 by Glynn Clements and the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General Public
  12. * License (>=v2). Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. *****************************************************************************/
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <math.h>
  19. #include <string.h>
  20. #include <grass/gis.h>
  21. #include <grass/imagery.h>
  22. #include <grass/gprojects.h>
  23. #include <grass/glocale.h>
  24. #include "gdal.h"
  25. static void list_formats(void)
  26. {
  27. /* -------------------------------------------------------------------- */
  28. /* List supported formats and exit. */
  29. /* code from GDAL 1.2.5 gcore/gdal_misc.cpp */
  30. /* Copyright (c) 1999, Frank Warmerdam */
  31. /* -------------------------------------------------------------------- */
  32. int iDr;
  33. fprintf(stdout, _("Supported Formats:\n"));
  34. for (iDr = 0; iDr < GDALGetDriverCount(); iDr++) {
  35. GDALDriverH hDriver = GDALGetDriver(iDr);
  36. const char *pszRWFlag;
  37. #ifdef GDAL_DCAP_RASTER
  38. /* Starting with GDAL 2.0, vector drivers can also be returned */
  39. /* Only keep raster drivers */
  40. if (!GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER, NULL))
  41. continue;
  42. #endif
  43. if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL))
  44. pszRWFlag = "rw+";
  45. else if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL))
  46. pszRWFlag = "rw";
  47. else
  48. continue;
  49. fprintf(stdout, " %s (%s): %s\n",
  50. GDALGetDriverShortName(hDriver),
  51. pszRWFlag, GDALGetDriverLongName(hDriver));
  52. }
  53. }
  54. static char *format_list(void)
  55. {
  56. char *buf, *p;
  57. int len = 0;
  58. int first = 1;
  59. int i;
  60. for (i = 0; i < GDALGetDriverCount(); i++) {
  61. GDALDriverH driver = GDALGetDriver(i);
  62. #ifdef GDAL_DCAP_RASTER
  63. /* Starting with GDAL 2.0, vector drivers can also be returned */
  64. /* Only keep raster drivers */
  65. if (!GDALGetMetadataItem(driver, GDAL_DCAP_RASTER, NULL))
  66. continue;
  67. #endif
  68. if (!GDALGetMetadataItem(driver, GDAL_DCAP_CREATE, NULL) &&
  69. !GDALGetMetadataItem(driver, GDAL_DCAP_CREATECOPY, NULL))
  70. continue;
  71. len += strlen(GDALGetDriverShortName(driver)) + 1;
  72. }
  73. buf = G_malloc(len);
  74. p = buf;
  75. for (i = 0; i < GDALGetDriverCount(); i++) {
  76. GDALDriverH driver = GDALGetDriver(i);
  77. const char *name;
  78. #ifdef GDAL_DCAP_RASTER
  79. /* Starting with GDAL 2.0, vector drivers can also be returned */
  80. /* Only keep raster drivers */
  81. if (!GDALGetMetadataItem(driver, GDAL_DCAP_RASTER, NULL))
  82. continue;
  83. #endif
  84. if (!GDALGetMetadataItem(driver, GDAL_DCAP_CREATE, NULL) &&
  85. !GDALGetMetadataItem(driver, GDAL_DCAP_CREATECOPY, NULL))
  86. continue;
  87. if (first)
  88. first = 0;
  89. else
  90. *p++ = ',';
  91. name = GDALGetDriverShortName(driver);
  92. strcpy(p, name);
  93. p += strlen(name);
  94. }
  95. *p++ = '\0';
  96. return buf;
  97. }
  98. static void print_status(void)
  99. {
  100. FILE *fp;
  101. struct Key_Value *key_val;
  102. const char *p;
  103. if (!G_find_file2("", "GDAL", G_mapset())) {
  104. fprintf(stdout, "Not using GDAL\n");
  105. return;
  106. }
  107. fp = G_fopen_old("", "GDAL", G_mapset());
  108. if (!fp)
  109. G_fatal_error(_("Unable to open GDAL file"));
  110. key_val = G_fread_key_value(fp);
  111. fclose(fp);
  112. p = G_find_key_value("directory", key_val);
  113. fprintf(stdout, "directory: %s\n", p ? p : "not set (default 'gdal')");
  114. p = G_find_key_value("extension", key_val);
  115. fprintf(stdout, "extension: %s\n", p ? p : "<none>");
  116. p = G_find_key_value("format", key_val);
  117. fprintf(stdout, "format: %s\n", p ? p : "not set (default GTiff)");
  118. p = G_find_key_value("options", key_val);
  119. fprintf(stdout, "options: %s\n", p ? p : "<none>");
  120. G_free_key_value(key_val);
  121. }
  122. static void check_format(const char *format)
  123. {
  124. GDALDriverH driver = GDALGetDriverByName(format);
  125. if (!driver)
  126. G_fatal_error(_("Format <%s> not supported"), format);
  127. if (GDALGetMetadataItem(driver, GDAL_DCAP_CREATE, NULL))
  128. return;
  129. if (GDALGetMetadataItem(driver, GDAL_DCAP_CREATECOPY, NULL)) {
  130. G_warning(_("Format <%s> does not support direct write"), format);
  131. return;
  132. }
  133. G_fatal_error(_("Format <%s> does not support writing"), format);
  134. }
  135. static void make_link(const char *dir, const char *ext,
  136. const char *format, char **options)
  137. {
  138. struct Key_Value *key_val = G_create_key_value();
  139. char *opt_str = NULL;
  140. FILE *fp;
  141. if (options && *options) {
  142. int n_opts = 0, opt_len = 0, i;
  143. char *p;
  144. for (i = 0; options[i]; i++) {
  145. n_opts++;
  146. opt_len += strlen(options[i]) + 1;
  147. }
  148. opt_str = G_malloc(opt_len);
  149. p = opt_str;
  150. for (i = 0; i < n_opts; i++) {
  151. if (i > 0)
  152. *p++ = ',';
  153. strcpy(p, options[i]);
  154. p += strlen(options[i]);
  155. }
  156. *p++ = '\0';
  157. }
  158. if (ext && ext[0] != '.') {
  159. char *p;
  160. G_asprintf(&p, ".%s", ext);
  161. ext = p;
  162. }
  163. if (dir)
  164. G_set_key_value("directory", dir, key_val);
  165. if (ext)
  166. G_set_key_value("extension", ext, key_val);
  167. if (format)
  168. G_set_key_value("format", format, key_val);
  169. if (opt_str)
  170. G_set_key_value("options", opt_str, key_val);
  171. fp = G_fopen_new("", "GDAL");
  172. if (!fp)
  173. G_fatal_error(_("Unable to create GDAL file"));
  174. if (G_fwrite_key_value(fp, key_val) < 0)
  175. G_fatal_error(_("Error writing GDAL file"));
  176. fclose(fp);
  177. }
  178. int main(int argc, char *argv[])
  179. {
  180. struct GModule *module;
  181. struct {
  182. struct Option *dir, *ext, *format, *opts;
  183. } parm;
  184. struct Flag *flag_f, *flag_r, *flag_p;
  185. G_gisinit(argv[0]);
  186. GDALAllRegister();
  187. module = G_define_module();
  188. G_add_keyword(_("raster"));
  189. G_add_keyword(_("export"));
  190. G_add_keyword(_("output"));
  191. G_add_keyword(_("external"));
  192. module->description =
  193. _("Redirects raster output to file utilizing GDAL library rather than storing in GRASS raster format.");
  194. parm.dir = G_define_option();
  195. parm.dir->key = "directory";
  196. parm.dir->description = _("Name of output directory");
  197. parm.dir->required = YES;
  198. parm.dir->type = TYPE_STRING;
  199. parm.dir->key_desc = "path";
  200. parm.ext = G_define_option();
  201. parm.ext->key = "extension";
  202. parm.ext->description = _("Extension for output files");
  203. parm.ext->required = NO;
  204. parm.ext->type = TYPE_STRING;
  205. parm.format = G_define_option();
  206. parm.format->key = "format";
  207. parm.format->description = _("Format of output files");
  208. parm.format->required = YES;
  209. parm.format->type = TYPE_STRING;
  210. parm.format->options = format_list();
  211. parm.opts = G_define_option();
  212. parm.opts->key = "options";
  213. parm.opts->description = _("Creation options");
  214. parm.opts->required = NO;
  215. parm.opts->multiple = YES;
  216. parm.opts->type = TYPE_STRING;
  217. flag_f = G_define_flag();
  218. flag_f->key = 'f';
  219. flag_f->description = _("List supported formats and exit");
  220. flag_f->guisection = _("Print");
  221. flag_f->suppress_required = YES;
  222. flag_r = G_define_flag();
  223. flag_r->key = 'r';
  224. flag_r->description = _("Cease using GDAL and revert to native output");
  225. flag_r->suppress_required = YES;
  226. flag_p = G_define_flag();
  227. flag_p->key = 'p';
  228. flag_p->description = _("Print current status");
  229. flag_p->guisection = _("Print");
  230. flag_p->suppress_required = YES;
  231. if (G_parser(argc, argv))
  232. exit(EXIT_FAILURE);
  233. if (flag_p->answer) {
  234. print_status();
  235. exit(EXIT_SUCCESS);
  236. }
  237. if (flag_f->answer) {
  238. list_formats();
  239. exit(EXIT_SUCCESS);
  240. }
  241. if (flag_r->answer) {
  242. G_remove("", "GDAL");
  243. exit(EXIT_SUCCESS);
  244. }
  245. if (parm.format->answer)
  246. check_format(parm.format->answer);
  247. make_link(parm.dir->answer, parm.ext->answer, parm.format->answer,
  248. parm.opts->answers);
  249. exit(EXIT_SUCCESS);
  250. }