main.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /****************************************************************************
  2. *
  3. * MODULE: r.out.gdal
  4. * AUTHOR(S): Vytautas Vebra <olivership@gmail.com>, Markus Metz
  5. * PURPOSE: Exports GRASS raster to GDAL suported formats;
  6. * based on GDAL library.
  7. * Replaces r.out.gdal.sh script which used the gdal_translate
  8. * executable and GDAL grass-format plugin.
  9. * COPYRIGHT: (C) 2006-2009 by 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. /* Undefine this if you do not want any extra funtion calls before G_parse() */
  17. #define __ALLOW_DYNAMIC_OPTIONS__
  18. #include <stdlib.h>
  19. #include <unistd.h>
  20. #include <float.h>
  21. #include <math.h>
  22. #include <string.h>
  23. #include <grass/gis.h>
  24. #include <grass/raster.h>
  25. #include <grass/imagery.h>
  26. #include <grass/gprojects.h>
  27. #include <grass/glocale.h>
  28. #include <grass/dbmi.h>
  29. #include "cpl_string.h"
  30. #include "local_proto.h"
  31. int range_check(double, double, GDALDataType);
  32. int nodataval_check(double, GDALDataType);
  33. double set_default_nodata_value(GDALDataType, double, double);
  34. void supported_formats(const char **formats)
  35. {
  36. /* Code taken from r.in.gdal */
  37. int iDr;
  38. dbString gdal_formats;
  39. db_init_string(&gdal_formats);
  40. if (*formats)
  41. fprintf(stdout, _("Supported formats:\n"));
  42. for (iDr = 0; iDr < GDALGetDriverCount(); iDr++) {
  43. GDALDriverH hDriver = GDALGetDriver(iDr);
  44. const char *pszRWFlag;
  45. #ifdef GDAL_DCAP_RASTER
  46. /* Starting with GDAL 2.0, vector drivers can also be returned */
  47. /* Only keep raster drivers */
  48. if (!GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER, NULL))
  49. continue;
  50. #endif
  51. if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL))
  52. pszRWFlag = "rw+";
  53. else if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL))
  54. pszRWFlag = "rw";
  55. else
  56. continue;
  57. if (*formats)
  58. fprintf(stdout, " %s (%s): %s\n",
  59. GDALGetDriverShortName(hDriver), pszRWFlag,
  60. GDALGetDriverLongName(hDriver));
  61. else {
  62. if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL) ||
  63. GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL)) {
  64. if (db_sizeof_string(&gdal_formats) > 0)
  65. db_append_string(&gdal_formats, ",");
  66. db_append_string(&gdal_formats,
  67. (char *)GDALGetDriverShortName(hDriver));
  68. }
  69. }
  70. }
  71. if (db_sizeof_string(&gdal_formats) > 0)
  72. *formats = G_store(db_get_string(&gdal_formats));
  73. return;
  74. }
  75. static void AttachMetadata(GDALDatasetH hDS, char **papszMetadataOptions)
  76. /* function taken from gdal_translate */
  77. {
  78. int nCount = CSLCount(papszMetadataOptions);
  79. int i;
  80. for (i = 0; i < nCount; i++) {
  81. char *pszKey = NULL;
  82. const char *pszValue;
  83. pszValue = CPLParseNameValue(papszMetadataOptions[i], &pszKey);
  84. GDALSetMetadataItem(hDS, pszKey, pszValue, NULL);
  85. CPLFree(pszKey);
  86. }
  87. CSLDestroy(papszMetadataOptions);
  88. }
  89. int main(int argc, char *argv[])
  90. {
  91. struct GModule *module;
  92. struct Flag *flag_l, *flag_c, *flag_m, *flag_f, *flag_t;
  93. struct Option *input, *format, *type, *output, *createopt, *metaopt,
  94. *nodataopt;
  95. struct Cell_head cellhead;
  96. struct Ref ref;
  97. const char *mapset, *gdal_formats = NULL;
  98. RASTER_MAP_TYPE maptype, testmaptype;
  99. int bHaveMinMax;
  100. double dfCellMin, export_min;
  101. double dfCellMax, export_max;
  102. struct FPRange sRange;
  103. int retval = 0;
  104. G_gisinit(argv[0]);
  105. module = G_define_module();
  106. module->description =
  107. _("Exports GRASS raster maps into GDAL supported formats.");
  108. G_add_keyword(_("raster"));
  109. G_add_keyword(_("export"));
  110. flag_l = G_define_flag();
  111. flag_l->key = 'l';
  112. flag_l->description = _("List supported output formats");
  113. flag_l->guisection = _("Print");
  114. flag_l->suppress_required = YES;
  115. flag_c = G_define_flag();
  116. flag_c->key = 'c';
  117. flag_c->label = _("Do not write GDAL standard colortable");
  118. flag_c->description = _("Only applicable to Byte or UInt16 data types");
  119. flag_c->guisection = _("Creation");
  120. flag_m = G_define_flag();
  121. flag_m->key = 'm';
  122. flag_m->label = _("Do not write non-standard metadata");
  123. flag_m->description = _("Enhances compatibility with other GIS software");
  124. flag_m->guisection = _("Creation");
  125. flag_t = G_define_flag();
  126. flag_t->key = 't';
  127. flag_t->label = _("Write raster attribute table");
  128. flag_t->description = _("Some export formats may not be supported");
  129. flag_f = G_define_flag();
  130. flag_f->key = 'f';
  131. flag_f->label = _("Force raster export despite any warnings of data loss");
  132. flag_f->description = _("Overrides nodata safety check");
  133. input = G_define_standard_option(G_OPT_R_INPUT);
  134. input->description = _("Name of raster map (or group) to export");
  135. output = G_define_standard_option(G_OPT_F_OUTPUT);
  136. output->description = _("Name for output raster file");
  137. format = G_define_option();
  138. format->key = "format";
  139. format->type = TYPE_STRING;
  140. format->description =
  141. _("Raster data format to write (case sensitive, see also -l flag)");
  142. #ifdef __ALLOW_DYNAMIC_OPTIONS__
  143. /* Init GDAL */
  144. GDALAllRegister();
  145. supported_formats(&gdal_formats);
  146. if (gdal_formats)
  147. format->options = G_store(gdal_formats);
  148. /* else
  149. * G_fatal_error (_("Unknown GIS formats")); */
  150. #else
  151. gdal_formats =
  152. "AAIGrid,BMP,BSB,DTED,ELAS,ENVI,FIT,GIF,GTiff,HFA,JPEG,MEM,MFF,MFF2,NITF,PAux,PNG,PNM,VRT,XPM";
  153. format->options = gdal_formats;
  154. #endif
  155. format->answer = "GTiff";
  156. format->required = YES;
  157. type = G_define_option();
  158. type->key = "type";
  159. type->type = TYPE_STRING;
  160. type->description = _("Data type");
  161. type->options =
  162. "Byte,Int16,UInt16,Int32,UInt32,Float32,Float64,CInt16,CInt32,CFloat32,CFloat64";
  163. type->required = NO;
  164. type->guisection = _("Creation");
  165. createopt = G_define_option();
  166. createopt->key = "createopt";
  167. createopt->type = TYPE_STRING;
  168. createopt->label =
  169. _("Creation option(s) to pass to the output format driver");
  170. createopt->description =
  171. _("In the form of \"NAME=VALUE\", separate multiple entries with a comma");
  172. createopt->multiple = YES;
  173. createopt->required = NO;
  174. createopt->guisection = _("Creation");
  175. metaopt = G_define_option();
  176. metaopt->key = "metaopt";
  177. metaopt->type = TYPE_STRING;
  178. metaopt->label = _("Metadata key(s) and value(s) to include");
  179. metaopt->description =
  180. _("In the form of \"META-TAG=VALUE\", separate multiple entries "
  181. "with a comma. Not supported by all output format drivers.");
  182. metaopt->multiple = YES;
  183. metaopt->required = NO;
  184. metaopt->guisection = _("Creation");
  185. nodataopt = G_define_option();
  186. nodataopt->key = "nodata";
  187. nodataopt->type = TYPE_DOUBLE;
  188. nodataopt->label =
  189. _("Assign a specified nodata value to output bands");
  190. nodataopt->description =
  191. _("If given, the nodata value is always written to metadata "
  192. "even if there are no NULL cells in the input band "
  193. "(enhances output compatibility).");
  194. nodataopt->multiple = NO;
  195. nodataopt->required = NO;
  196. nodataopt->guisection = _("Creation");
  197. if (G_parser(argc, argv))
  198. exit(EXIT_FAILURE);
  199. #ifndef __ALLOW_DYNAMIC_OPTIONS__
  200. /* Init GDAL */
  201. GDALAllRegister();
  202. #endif
  203. if (flag_l->answer) {
  204. supported_formats(&gdal_formats);
  205. exit(EXIT_SUCCESS);
  206. }
  207. /* Find input GRASS raster.. */
  208. mapset = G_find_raster2(input->answer, "");
  209. if (mapset != NULL) {
  210. /* Add input to "group". "Group" with 1 raster (band) will exist only in memory. */
  211. I_init_group_ref(&ref);
  212. I_add_file_to_group_ref(input->answer, mapset, &ref);
  213. }
  214. else {
  215. /* Maybe input is group. Try to read group file */
  216. if (I_get_group_ref(input->answer, &ref) != 1)
  217. G_fatal_error(_("Raster map or group <%s> not found"),
  218. input->answer);
  219. }
  220. if (ref.nfiles == 0)
  221. G_fatal_error(_("No raster maps in group <%s>"), input->answer);
  222. /* Read project and region data */
  223. struct Key_Value *projinfo = G_get_projinfo();
  224. struct Key_Value *projunits = G_get_projunits();
  225. char *srswkt = GPJ_grass_to_wkt(projinfo, projunits, 0, 0);
  226. G_get_window(&cellhead);
  227. /* Try to create raster data drivers. If failed - exit. */
  228. GDALDriverH hDriver = NULL, hMEMDriver = NULL;
  229. hDriver = GDALGetDriverByName(format->answer);
  230. if (hDriver == NULL)
  231. G_fatal_error(_("Unable to get <%s> driver"), format->answer);
  232. /* Does driver support GDALCreate ? */
  233. if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL) == NULL) {
  234. /* If not - create MEM driver for intermediate dataset.
  235. * Check if raster can be created at all (with GDALCreateCopy) */
  236. if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL)) {
  237. G_message(_("Driver <%s> does not support direct writing. "
  238. "Using MEM driver for intermediate dataset."),
  239. format->answer);
  240. hMEMDriver = GDALGetDriverByName("MEM");
  241. if (hMEMDriver == NULL)
  242. G_fatal_error(_("Unable to get in-memory raster driver"));
  243. }
  244. else
  245. G_fatal_error(_("Driver <%s> does not support creating rasters"),
  246. format->answer);
  247. }
  248. /* Determine GDAL data type */
  249. GDALDataType datatype = GDT_Unknown;
  250. maptype = CELL_TYPE;
  251. if (type->answer) {
  252. /* reduce number of strcmps ... */
  253. if (type->answer[0] == 'B') {
  254. datatype = GDT_Byte;
  255. maptype = CELL_TYPE;
  256. }
  257. else if (type->answer[0] == 'I') {
  258. if (strcmp(type->answer, "Int16") == 0) {
  259. datatype = GDT_Int16;
  260. maptype = CELL_TYPE;
  261. }
  262. else if (strcmp(type->answer, "Int32") == 0) {
  263. datatype = GDT_Int32;
  264. maptype = CELL_TYPE;
  265. }
  266. }
  267. else if (type->answer[0] == 'U') {
  268. if (strcmp(type->answer, "UInt16") == 0) {
  269. datatype = GDT_UInt16;
  270. maptype = CELL_TYPE;
  271. }
  272. else if (strcmp(type->answer, "UInt32") == 0) {
  273. datatype = GDT_UInt32;
  274. maptype = DCELL_TYPE;
  275. }
  276. }
  277. else if (type->answer[0] == 'F') {
  278. if (strcmp(type->answer, "Float32") == 0) {
  279. datatype = GDT_Float32;
  280. maptype = FCELL_TYPE;
  281. }
  282. else if (strcmp(type->answer, "Float64") == 0) {
  283. datatype = GDT_Float64;
  284. maptype = DCELL_TYPE;
  285. }
  286. }
  287. else if (type->answer[0] == 'C') {
  288. if (strcmp(type->answer, "CInt16") == 0) {
  289. datatype = GDT_CInt16;
  290. maptype = CELL_TYPE;
  291. }
  292. else if (strcmp(type->answer, "CInt32") == 0) {
  293. datatype = GDT_CInt32;
  294. maptype = CELL_TYPE;
  295. }
  296. else if (strcmp(type->answer, "CFloat32") == 0) {
  297. datatype = GDT_CFloat32;
  298. maptype = FCELL_TYPE;
  299. }
  300. else if (strcmp(type->answer, "CFloat64") == 0) {
  301. datatype = GDT_CFloat64;
  302. maptype = DCELL_TYPE;
  303. }
  304. }
  305. }
  306. /* get min/max values */
  307. int band;
  308. bHaveMinMax = TRUE;
  309. export_min = TYPE_FLOAT64_MIN;
  310. export_max = TYPE_FLOAT64_MAX;
  311. for (band = 0; band < ref.nfiles; band++) {
  312. if (Rast_read_fp_range
  313. (ref.file[band].name, ref.file[band].mapset, &sRange) == -1) {
  314. bHaveMinMax = FALSE;
  315. G_warning(_("Could not read data range of raster <%s>"),
  316. ref.file[band].name);
  317. }
  318. else {
  319. Rast_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax);
  320. if (band == 0) {
  321. export_min = dfCellMin;
  322. export_max = dfCellMax;
  323. }
  324. else {
  325. if (export_min > dfCellMin)
  326. export_min = dfCellMin;
  327. if (export_max < dfCellMax)
  328. export_max = dfCellMax;
  329. }
  330. }
  331. G_debug(3, "Range of <%s>: min: %f, max: %f", ref.file[band].name,
  332. dfCellMin, dfCellMax);
  333. }
  334. if (bHaveMinMax == FALSE) {
  335. export_min = TYPE_FLOAT64_MIN;
  336. export_max = TYPE_FLOAT64_MAX;
  337. }
  338. G_debug(3, "Total range: min: %f, max: %f", export_min, export_max);
  339. /* GDAL datatype not set by user, determine suitable datatype */
  340. if (datatype == GDT_Unknown) {
  341. /* Use raster data type from first GRASS raster in a group */
  342. maptype = Rast_map_type(ref.file[0].name, ref.file[0].mapset);
  343. if (maptype == FCELL_TYPE) {
  344. datatype = GDT_Float32;
  345. }
  346. else if (maptype == DCELL_TYPE) {
  347. datatype = GDT_Float64;
  348. }
  349. else {
  350. /* Special tricks for GeoTIFF color table support and such */
  351. if (export_min >= TYPE_BYTE_MIN && export_max <= TYPE_BYTE_MAX) {
  352. datatype = GDT_Byte;
  353. }
  354. else {
  355. if (export_min >= TYPE_UINT16_MIN &&
  356. export_max <= TYPE_UINT16_MAX) {
  357. datatype = GDT_UInt16;
  358. }
  359. else if (export_min >= TYPE_INT16_MIN &&
  360. export_max <= TYPE_INT16_MAX) {
  361. datatype = GDT_Int16;
  362. }
  363. else {
  364. datatype = GDT_Int32; /* need to fine tune this more? */
  365. }
  366. }
  367. }
  368. }
  369. /* got a GDAL datatype, report to user */
  370. G_verbose_message(_("Exporting to GDAL data type: %s"),
  371. GDALGetDataTypeName(datatype));
  372. G_debug(3, "Input map datatype=%s\n",
  373. (maptype == CELL_TYPE ? "CELL" :
  374. (maptype == DCELL_TYPE ? "DCELL" :
  375. (maptype == FCELL_TYPE ? "FCELL" : "??"))));
  376. /* if GDAL datatype set by user, do checks */
  377. if (type->answer) {
  378. /* Check if raster data range is outside of the range of
  379. * given GDAL datatype, not even overlapping */
  380. if (range_check(export_min, export_max, datatype))
  381. G_fatal_error(_("Raster export would result in complete data loss, aborting."));
  382. /* Precision tests */
  383. for (band = 0; band < ref.nfiles; band++) {
  384. testmaptype =
  385. Rast_map_type(ref.file[band].name, ref.file[band].mapset);
  386. /* Exporting floating point rasters to some integer type ? */
  387. if ((testmaptype == FCELL_TYPE || testmaptype == DCELL_TYPE) &&
  388. (datatype == GDT_Byte || datatype == GDT_Int16 ||
  389. datatype == GDT_UInt16 || datatype == GDT_Int32 ||
  390. datatype == GDT_UInt32)) {
  391. G_warning(_("Precision loss: Raster map <%s> of type %s to be exported as %s. "
  392. "This can be avoided by using %s."),
  393. ref.file[band].name,
  394. (maptype == FCELL_TYPE ? "FCELL" : "DCELL"),
  395. GDALGetDataTypeName(datatype),
  396. (maptype == FCELL_TYPE ? "Float32" : "Float64"));
  397. retval = -1;
  398. }
  399. /* Exporting CELL with large values to GDT_Float32 ? Cap is 2^24 */
  400. if (testmaptype == CELL_TYPE && datatype == GDT_Float32 &&
  401. (dfCellMin < -16777216 || dfCellMax > 16777216)) {
  402. G_warning(_("Precision loss: The range of <%s> can not be "
  403. "accurately preserved with GDAL datatype Float32. "
  404. "This can be avoided by exporting to Int32 or Float64."),
  405. ref.file[band].name);
  406. retval = -1;
  407. }
  408. /* Exporting DCELL to GDT_Float32 ? */
  409. if (testmaptype == DCELL_TYPE && datatype == GDT_Float32) {
  410. G_warning(_("Precision loss: Float32 can not preserve the "
  411. "DCELL precision of raster <%s>. "
  412. "This can be avoided by using Float64"),
  413. ref.file[band].name);
  414. retval = -1;
  415. }
  416. }
  417. if (retval == -1) {
  418. if (flag_f->answer)
  419. G_warning(_("Forcing raster export"));
  420. else
  421. G_fatal_error(_("Raster export aborted. "
  422. "To override data loss check, use the -%c flag"), flag_f->key);
  423. }
  424. }
  425. /* Nodata value */
  426. double nodataval;
  427. int default_nodataval = 1;
  428. /* User-specified nodata-value ? */
  429. if (nodataopt->answer) {
  430. nodataval = atof(nodataopt->answer);
  431. default_nodataval = 0;
  432. /* Check if given nodata value can be represented by selected GDAL datatype */
  433. if (nodataval_check(nodataval, datatype)) {
  434. G_fatal_error(_("Raster export aborted."));
  435. }
  436. }
  437. /* Set reasonable default nodata value */
  438. else {
  439. nodataval =
  440. set_default_nodata_value(datatype, export_min, export_max);
  441. }
  442. /* exact range and nodata checks for each band */
  443. G_message(_("Checking GDAL data type and nodata value..."));
  444. for (band = 0; band < ref.nfiles; band++) {
  445. if (ref.nfiles > 1) {
  446. G_verbose_message(_("Checking options for raster map <%s> (band %d)..."),
  447. G_fully_qualified_name(ref.file[band].name,
  448. ref.file[band].mapset),
  449. band + 1);
  450. }
  451. retval = exact_checks
  452. (datatype, ref.file[band].name, ref.file[band].mapset,
  453. &cellhead, maptype, nodataval, nodataopt->key,
  454. default_nodataval);
  455. /* nodata value is present in the data to be exported */
  456. if (retval == -1) {
  457. if (flag_f->answer)
  458. G_warning(_("Forcing raster export."));
  459. else
  460. G_fatal_error(_("Raster export aborted."));
  461. }
  462. /* data don't fit into range of GDAL datatype */
  463. else if (retval == -2) {
  464. G_fatal_error(_("Raster export aborted."));
  465. }
  466. }
  467. /* Create dataset for output with target driver or, if needed, with in-memory driver */
  468. char **papszOptions = NULL;
  469. /* Parse dataset creation options */
  470. if (createopt->answer) {
  471. int i;
  472. i = 0;
  473. while (createopt->answers[i]) {
  474. papszOptions = CSLAddString(papszOptions, createopt->answers[i]);
  475. i++;
  476. }
  477. }
  478. GDALDatasetH hCurrDS = NULL, hMEMDS = NULL, hDstDS = NULL;
  479. if (hMEMDriver) {
  480. hMEMDS =
  481. GDALCreate(hMEMDriver, "", cellhead.cols, cellhead.rows,
  482. ref.nfiles, datatype, papszOptions);
  483. if (hMEMDS == NULL)
  484. G_fatal_error(_("Unable to create dataset using "
  485. "memory raster driver"));
  486. hCurrDS = hMEMDS;
  487. }
  488. else {
  489. hDstDS =
  490. GDALCreate(hDriver, output->answer, cellhead.cols, cellhead.rows,
  491. ref.nfiles, datatype, papszOptions);
  492. if (hDstDS == NULL)
  493. G_fatal_error(_("Unable to create <%s> dataset using <%s> driver"),
  494. output->answer, format->answer);
  495. hCurrDS = hDstDS;
  496. }
  497. /* Set Geo Transform */
  498. double adfGeoTransform[6];
  499. adfGeoTransform[0] = cellhead.west;
  500. adfGeoTransform[1] = cellhead.ew_res;
  501. adfGeoTransform[2] = 0.0;
  502. adfGeoTransform[3] = cellhead.north;
  503. adfGeoTransform[4] = 0.0;
  504. adfGeoTransform[5] = -1 * cellhead.ns_res;
  505. if (GDALSetGeoTransform(hCurrDS, adfGeoTransform) >= CE_Failure)
  506. G_warning(_("Unable to set geo transform"));
  507. /* Set Projection */
  508. CPLErr ret = CE_None;
  509. if (srswkt)
  510. ret = GDALSetProjection(hCurrDS, srswkt);
  511. if (!srswkt || ret == CE_Failure)
  512. G_warning(_("Unable to set projection"));
  513. /* Add metadata */
  514. AttachMetadata(hCurrDS, metaopt->answers);
  515. if (strcmp(format->answer, "GTiff") == 0) {
  516. char *pszKey;
  517. char *pszValue;
  518. pszKey = "TIFFTAG_SOFTWARE";
  519. G_asprintf(&pszValue, "GRASS GIS %s with GDAL %d.%d.%d",
  520. GRASS_VERSION_NUMBER,
  521. GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR, GDAL_VERSION_REV);
  522. GDALSetMetadataItem(hCurrDS, pszKey, pszValue, NULL);
  523. G_free(pszValue);
  524. }
  525. else if (!flag_m->answer) {
  526. char *pszKey;
  527. char *pszValue;
  528. pszKey = "SOFTWARE";
  529. G_asprintf(&pszValue, "GRASS GIS %s with GDAL %d.%d.%d",
  530. GRASS_VERSION_NUMBER,
  531. GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR, GDAL_VERSION_REV);
  532. GDALSetMetadataItem(hCurrDS, pszKey, pszValue, NULL);
  533. G_free(pszValue);
  534. }
  535. /* Export to GDAL raster */
  536. G_message(_("Exporting raster data to %s format..."), format->answer);
  537. for (band = 0; band < ref.nfiles; band++) {
  538. if (ref.nfiles > 1) {
  539. G_verbose_message(_("Exporting raster map <%s> (band %d)..."),
  540. G_fully_qualified_name(ref.file[band].name,
  541. ref.file[band].mapset),
  542. band + 1);
  543. }
  544. retval = export_band
  545. (hCurrDS, band + 1, ref.file[band].name,
  546. ref.file[band].mapset, &cellhead, maptype, nodataval,
  547. flag_c->answer, flag_m->answer, (nodataopt->answer != NULL));
  548. /* read/write error */
  549. if (retval == -1) {
  550. G_warning(_("Unable to export raster map <%s>"),
  551. ref.file[band].name);
  552. }
  553. else if (flag_t->answer) {
  554. retval = export_attr(hCurrDS, band + 1, ref.file[band].name,
  555. ref.file[band].mapset, maptype);
  556. }
  557. }
  558. /* Finaly create user requested raster format from memory raster
  559. * if in-memory driver was used */
  560. if (hMEMDS) {
  561. hDstDS =
  562. GDALCreateCopy(hDriver, output->answer, hMEMDS, FALSE,
  563. papszOptions, NULL, NULL);
  564. if (hDstDS == NULL)
  565. G_fatal_error(_("Unable to create raster map <%s> using driver <%s>"),
  566. output->answer, format->answer);
  567. }
  568. GDALClose(hDstDS);
  569. if (hMEMDS)
  570. GDALClose(hMEMDS);
  571. CSLDestroy(papszOptions);
  572. G_done_msg("File <%s> created.", output->answer);
  573. exit(EXIT_SUCCESS);
  574. }
  575. int range_check(double min, double max, GDALDataType datatype)
  576. {
  577. /* what accuracy to use to print min max for FLOAT32 and FLOAT64? %g enough? */
  578. switch (datatype) {
  579. case GDT_Byte:
  580. if (max < TYPE_BYTE_MIN || min > TYPE_BYTE_MAX) {
  581. G_warning(_("Selected GDAL datatype does not cover data range."));
  582. G_warning(_("GDAL datatype: %s, range: %d - %d"),
  583. GDALGetDataTypeName(datatype), TYPE_BYTE_MIN,
  584. TYPE_BYTE_MAX);
  585. G_warning(_("Range to be exported: %g - %g"), min, max);
  586. return 1;
  587. }
  588. else
  589. return 0;
  590. case GDT_UInt16:
  591. if (max < TYPE_UINT16_MIN || min > TYPE_UINT16_MAX) {
  592. G_warning(_("Selected GDAL datatype does not cover data range."));
  593. G_warning(_("GDAL datatype: %s, range: %d - %d"),
  594. GDALGetDataTypeName(datatype), TYPE_UINT16_MIN,
  595. TYPE_UINT16_MAX);
  596. G_warning(_("Range to be exported: %g - %g"), min, max);
  597. return 1;
  598. }
  599. else
  600. return 0;
  601. case GDT_Int16:
  602. case GDT_CInt16:
  603. if (max < TYPE_INT16_MIN || min > TYPE_INT16_MAX) {
  604. G_warning(_("Selected GDAL datatype does not cover data range."));
  605. G_warning(_("GDAL datatype: %s, range: %d - %d"),
  606. GDALGetDataTypeName(datatype), TYPE_INT16_MIN,
  607. TYPE_INT16_MAX);
  608. G_warning(_("Range to be exported: %g - %g"), min, max);
  609. return 1;
  610. }
  611. else
  612. return 0;
  613. case GDT_Int32:
  614. case GDT_CInt32:
  615. if (max < TYPE_INT32_MIN || min > TYPE_INT32_MAX) {
  616. G_warning(_("Selected GDAL datatype does not cover data range."));
  617. G_warning(_("GDAL datatype: %s, range: %d - %d"),
  618. GDALGetDataTypeName(datatype), TYPE_INT32_MIN,
  619. TYPE_INT32_MAX);
  620. G_warning(_("Range to be exported: %g - %g"), min, max);
  621. return 1;
  622. }
  623. else
  624. return 0;
  625. case GDT_UInt32:
  626. if (max < TYPE_UINT32_MIN || min > TYPE_UINT32_MAX) {
  627. G_warning(_("Selected GDAL datatype does not cover data range."));
  628. G_warning(_("GDAL datatype: %s, range: %u - %u"),
  629. GDALGetDataTypeName(datatype), TYPE_UINT32_MIN,
  630. TYPE_UINT32_MAX);
  631. G_warning(_("Range to be exported: %g - %g"), min, max);
  632. return 1;
  633. }
  634. else
  635. return 0;
  636. case GDT_Float32:
  637. case GDT_CFloat32:
  638. if (max < TYPE_FLOAT32_MIN || min > TYPE_FLOAT32_MAX) {
  639. G_warning(_("Selected GDAL datatype does not cover data range."));
  640. G_warning(_("GDAL datatype: %s, range: %g - %g"),
  641. GDALGetDataTypeName(datatype), TYPE_FLOAT32_MIN,
  642. TYPE_FLOAT32_MAX);
  643. G_warning(_("Range to be exported: %g - %g"), min, max);
  644. return 1;
  645. }
  646. else
  647. return 0;
  648. case GDT_Float64:
  649. case GDT_CFloat64:
  650. /* not needed because FLOAT64 should always cover the data range */
  651. return 0;
  652. default:
  653. return 0;
  654. }
  655. }
  656. int nodataval_check(double nodataval, GDALDataType datatype)
  657. {
  658. switch (datatype) {
  659. case GDT_Byte:
  660. /* the additional cast to CELL is what happens in export_band()
  661. * accordingly below for the other GDAL types */
  662. if (nodataval != (double)(GByte)(CELL) nodataval) {
  663. G_warning(_("Mismatch between metadata nodata value and actual nodata value in exported raster: "
  664. "specified nodata value %g gets converted to %d by selected GDAL datatype."),
  665. nodataval, (GByte)(CELL) nodataval);
  666. G_warning(_("GDAL datatype: %s, valid range: %d - %d"),
  667. GDALGetDataTypeName(datatype), TYPE_BYTE_MIN,
  668. TYPE_BYTE_MAX);
  669. return 1;
  670. }
  671. else
  672. return 0;
  673. case GDT_UInt16:
  674. if (nodataval != (double)(GUInt16)(CELL) nodataval) {
  675. G_warning(_("Mismatch between metadata nodata value and actual nodata value in exported raster: "
  676. "specified nodata value %g gets converted to %d by selected GDAL datatype."),
  677. nodataval, (GUInt16)(CELL) nodataval);
  678. G_warning(_("GDAL datatype: %s, valid range: %u - %u"),
  679. GDALGetDataTypeName(datatype), TYPE_UINT16_MIN,
  680. TYPE_UINT16_MAX);
  681. return 1;
  682. }
  683. else
  684. return 0;
  685. case GDT_Int16:
  686. case GDT_CInt16:
  687. if (nodataval != (double)(GInt16)(CELL) nodataval) {
  688. G_warning(_("Mismatch between metadata nodata value and actual nodata value in exported raster: "
  689. "specified nodata value %g gets converted to %d by selected GDAL datatype."),
  690. nodataval, (GInt16)(CELL) nodataval);
  691. G_warning(_("GDAL datatype: %s, valid range: %d - %d"),
  692. GDALGetDataTypeName(datatype), TYPE_INT16_MIN,
  693. TYPE_INT16_MAX);
  694. return 1;
  695. }
  696. else
  697. return 0;
  698. case GDT_UInt32:
  699. if (nodataval != (double)(GUInt32)(DCELL) nodataval) {
  700. G_warning(_("Mismatch between metadata nodata value and actual nodata value in exported raster: "
  701. "specified nodata value %g gets converted to %d by selected GDAL datatype."),
  702. nodataval, (GUInt32)(DCELL) nodataval);
  703. G_warning(_("GDAL datatype: %s, valid range: %u - %u"),
  704. GDALGetDataTypeName(datatype), TYPE_UINT32_MIN,
  705. TYPE_UINT32_MAX);
  706. return 1;
  707. }
  708. else
  709. return 0;
  710. case GDT_Int32:
  711. case GDT_CInt32:
  712. /* GInt32 is equal to CELL, but that may change in the future */
  713. if (nodataval != (double)(GInt32)(CELL) nodataval) {
  714. G_warning(_("Mismatch between metadata nodata value and actual nodata value in exported raster: "
  715. "specified nodata value %g gets converted to %d by selected GDAL datatype."),
  716. nodataval, (GInt32)(CELL) nodataval);
  717. G_warning(_("GDAL datatype: %s, valid range: %d - %d"),
  718. GDALGetDataTypeName(datatype), TYPE_INT32_MIN,
  719. TYPE_INT32_MAX);
  720. return 1;
  721. }
  722. else
  723. return 0;
  724. case GDT_Float32:
  725. case GDT_CFloat32:
  726. if (nodataval != (double)(float) nodataval) {
  727. G_warning(_("Mismatch between metadata nodata value and actual nodata value in exported raster: "
  728. "specified nodata value %g gets converted to %g by selected GDAL datatype."),
  729. nodataval, (float) nodataval);
  730. G_warning(_("GDAL datatype: %s, valid range: %g - %g"),
  731. GDALGetDataTypeName(datatype), TYPE_FLOAT32_MIN,
  732. TYPE_FLOAT32_MAX);
  733. return 1;
  734. }
  735. else
  736. return 0;
  737. case GDT_Float64:
  738. case GDT_CFloat64:
  739. /* not needed because FLOAT64 is equal to double */
  740. return 0;
  741. default:
  742. return 0;
  743. }
  744. }
  745. double set_default_nodata_value(GDALDataType datatype, double min, double max)
  746. {
  747. switch (datatype) {
  748. case GDT_Byte:
  749. if (max < TYPE_BYTE_MAX)
  750. return (double)TYPE_BYTE_MAX;
  751. else if (min > TYPE_BYTE_MIN)
  752. return (double)TYPE_BYTE_MIN;
  753. else
  754. return (double)TYPE_BYTE_MAX;
  755. case GDT_UInt16:
  756. if (max < TYPE_UINT16_MAX)
  757. return (double)TYPE_UINT16_MAX;
  758. else if (min > TYPE_UINT16_MIN)
  759. return (double)TYPE_UINT16_MIN;
  760. else
  761. return (double)TYPE_UINT16_MAX;
  762. case GDT_Int16:
  763. case GDT_CInt16:
  764. if (min > TYPE_INT16_MIN)
  765. return (double)TYPE_INT16_MIN;
  766. else if (max < TYPE_INT16_MAX)
  767. return (double)TYPE_INT16_MAX;
  768. else
  769. return (double)TYPE_INT16_MIN;
  770. case GDT_UInt32:
  771. if (max < TYPE_UINT32_MAX)
  772. return (double)TYPE_UINT32_MAX;
  773. else if (min > TYPE_UINT32_MIN)
  774. return (double)TYPE_UINT32_MIN;
  775. else
  776. return (double)TYPE_UINT32_MAX;
  777. case GDT_Int32:
  778. case GDT_CInt32:
  779. if (min > TYPE_INT32_MIN)
  780. return (double)TYPE_INT32_MIN;
  781. else if (max < TYPE_INT32_MAX)
  782. return (double)TYPE_INT32_MAX;
  783. else
  784. return (double)TYPE_INT32_MIN;
  785. case GDT_Float32:
  786. case GDT_CFloat32:
  787. return 0.0 / 0.0;
  788. case GDT_Float64:
  789. case GDT_CFloat64:
  790. return 0.0 / 0.0;
  791. default:
  792. return 0;
  793. }
  794. }