gdal.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. /*!
  2. \file lib/raster/gdal.c
  3. \brief Raster Library - Utilization of GDAL library.
  4. (C) 2010 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Glynn Clements
  8. */
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <grass/config.h>
  13. #include <grass/gis.h>
  14. #include <grass/raster.h>
  15. #include <grass/gprojects.h>
  16. #include <grass/glocale.h>
  17. #include "R.h"
  18. #ifndef HAVE_GDAL
  19. #undef GDAL_LINK
  20. #endif
  21. #ifdef GDAL_LINK
  22. #ifdef GDAL_DYNAMIC
  23. # if defined(__unix) || defined(__unix__)
  24. # include <dlfcn.h>
  25. # endif
  26. # ifdef _WIN32
  27. # include <windows.h>
  28. # endif
  29. #endif
  30. static void CPL_STDCALL(*pGDALAllRegister) (void);
  31. static void CPL_STDCALL(*pGDALClose) (GDALDatasetH);
  32. static GDALRasterBandH CPL_STDCALL(*pGDALGetRasterBand) (GDALDatasetH, int);
  33. static GDALDatasetH CPL_STDCALL(*pGDALOpen) (const char *pszFilename,
  34. GDALAccess eAccess);
  35. static CPLErr CPL_STDCALL(*pGDALRasterIO) (GDALRasterBandH hRBand,
  36. GDALRWFlag eRWFlag, int nDSXOff,
  37. int nDSYOff, int nDSXSize,
  38. int nDSYSize, void *pBuffer,
  39. int nBXSize, int nBYSize,
  40. GDALDataType eBDataType,
  41. int nPixelSpace, int nLineSpace);
  42. static GDALDriverH CPL_STDCALL(*pGDALGetDriverByName) (const char *);
  43. static const char *CPL_STDCALL(*pGDALGetMetadataItem) (GDALMajorObjectH,
  44. const char *,
  45. const char *);
  46. static GDALDatasetH CPL_STDCALL(*pGDALCreate) (GDALDriverH hDriver,
  47. const char *, int, int, int,
  48. GDALDataType, char **);
  49. static GDALDatasetH CPL_STDCALL(*pGDALCreateCopy) (GDALDriverH, const char *,
  50. GDALDatasetH, int, char **,
  51. GDALProgressFunc, void *);
  52. static CPLErr CPL_STDCALL(*pGDALSetRasterNoDataValue) (GDALRasterBandH,
  53. double);
  54. static CPLErr CPL_STDCALL(*pGDALSetGeoTransform) (GDALDatasetH, double *);
  55. static CPLErr CPL_STDCALL(*pGDALSetProjection) (GDALDatasetH, const char *);
  56. static const char *CPL_STDCALL(*pGDALGetDriverShortName) (GDALDriverH);
  57. static GDALDriverH CPL_STDCALL(*pGDALGetDatasetDriver) (GDALDatasetH);
  58. #if GDAL_DYNAMIC
  59. # if defined(__unix) && !defined(__unix__)
  60. # define __unix__ __unix
  61. # endif
  62. static void *library_h;
  63. static void *get_symbol(const char *name)
  64. {
  65. void *sym;
  66. # ifdef __unix__
  67. sym = dlsym(library_h, name);
  68. # endif
  69. # ifdef _WIN32
  70. sym = GetProcAddress((HINSTANCE) library_h, name);
  71. # endif
  72. if (!sym)
  73. G_fatal_error(_("Unable to locate symbol <%s>"), name);
  74. return sym;
  75. }
  76. static void try_load_library(const char *name)
  77. {
  78. # ifdef __unix__
  79. library_h = dlopen(name, RTLD_NOW);
  80. # endif
  81. # ifdef _WIN32
  82. library_h = LoadLibrary(name);
  83. # endif
  84. }
  85. static void load_library(void)
  86. {
  87. static const char *const candidates[] = {
  88. # ifdef __unix__
  89. "libgdal.so.26", /* GDAL 3.0 */
  90. "libgdal.so.20",
  91. "libgdal.so.1",
  92. "libgdal.1.1.so",
  93. "gdal.1.0.so",
  94. "gdal.so.1.0",
  95. "libgdal.so",
  96. "libgdal1.6.0.so",
  97. "libgdal1.7.0.so",
  98. # endif
  99. # ifdef _WIN32
  100. "gdal300.dll",
  101. "gdal204.dll",
  102. "gdal203.dll",
  103. "gdal202.dll",
  104. "gdal201.dll",
  105. "gdal200.dll",
  106. "gdal111.dll",
  107. "gdal110.dll",
  108. "gdal19.dll",
  109. "gdal18.dll",
  110. "gdal17.dll",
  111. "gdal16.dll",
  112. "gdal15.dll",
  113. "gdal11.dll",
  114. "gdal.1.0.dll",
  115. "libgdal-1.dll",
  116. "gdal.dll",
  117. # endif
  118. NULL
  119. };
  120. int i;
  121. for (i = 0; candidates[i]; i++) {
  122. try_load_library(candidates[i]);
  123. if (library_h) {
  124. G_debug(3, "found %s", candidates[i]);
  125. return;
  126. }
  127. }
  128. G_fatal_error(_("Unable to load GDAL library"));
  129. }
  130. static void init_gdal(void)
  131. {
  132. load_library();
  133. # if defined(_WIN32) && !defined(_WIN64)
  134. pGDALAllRegister = get_symbol("_GDALAllRegister@0");
  135. pGDALOpen = get_symbol("_GDALOpen@8");
  136. pGDALClose = get_symbol("_GDALClose@4");
  137. pGDALGetRasterBand = get_symbol("_GDALGetRasterBand@8");
  138. pGDALRasterIO = get_symbol("_GDALRasterIO@48");
  139. pGDALGetDriverByName = get_symbol("_GDALGetDriverByName@4");
  140. pGDALGetMetadataItem = get_symbol("_GDALGetMetadataItem@12");
  141. pGDALCreate = get_symbol("_GDALCreate@28");
  142. pGDALCreateCopy = get_symbol("_GDALCreateCopy@28");
  143. pGDALSetRasterNoDataValue = get_symbol("_GDALSetRasterNoDataValue@12");
  144. pGDALSetGeoTransform = get_symbol("_GDALSetGeoTransform@8");
  145. pGDALSetProjection = get_symbol("_GDALSetProjection@8");
  146. pGDALGetDriverShortName = get_symbol("_GDALGetDriverShortName@4");
  147. pGDALGetDatasetDriver = get_symbol("_GDALGetDatasetDriver@4");
  148. #else
  149. pGDALAllRegister = get_symbol("GDALAllRegister");
  150. pGDALOpen = get_symbol("GDALOpen");
  151. pGDALClose = get_symbol("GDALClose");
  152. pGDALGetRasterBand = get_symbol("GDALGetRasterBand");
  153. pGDALRasterIO = get_symbol("GDALRasterIO");
  154. pGDALGetDriverByName = get_symbol("GDALGetDriverByName");
  155. pGDALGetMetadataItem = get_symbol("GDALGetMetadataItem");
  156. pGDALCreate = get_symbol("GDALCreate");
  157. pGDALCreateCopy = get_symbol("GDALCreateCopy");
  158. pGDALSetRasterNoDataValue = get_symbol("GDALSetRasterNoDataValue");
  159. pGDALSetGeoTransform = get_symbol("GDALSetGeoTransform");
  160. pGDALSetProjection = get_symbol("GDALSetProjection");
  161. pGDALGetDriverShortName = get_symbol("GDALGetDriverShortName");
  162. pGDALGetDatasetDriver = get_symbol("GDALGetDatasetDriver");
  163. #endif
  164. }
  165. #else /* GDAL_DYNAMIC */
  166. static void init_gdal(void)
  167. {
  168. pGDALAllRegister = &GDALAllRegister;
  169. pGDALOpen = &GDALOpen;
  170. pGDALClose = &GDALClose;
  171. pGDALGetRasterBand = &GDALGetRasterBand;
  172. pGDALRasterIO = &GDALRasterIO;
  173. pGDALGetDriverByName = &GDALGetDriverByName;
  174. pGDALGetMetadataItem = &GDALGetMetadataItem;
  175. pGDALCreate = &GDALCreate;
  176. pGDALCreateCopy = &GDALCreateCopy;
  177. pGDALSetRasterNoDataValue = &GDALSetRasterNoDataValue;
  178. pGDALSetGeoTransform = &GDALSetGeoTransform;
  179. pGDALSetProjection = &GDALSetProjection;
  180. pGDALGetDriverShortName = &GDALGetDriverShortName;
  181. pGDALGetDatasetDriver = &GDALGetDatasetDriver;
  182. }
  183. #endif /* GDAL_DYNAMIC */
  184. #endif /* GDAL_LINK */
  185. /*!
  186. \brief Initialization
  187. Register all GDAL drivers.
  188. */
  189. void Rast_init_gdal(void)
  190. {
  191. #ifdef GDAL_LINK
  192. static int initialized;
  193. if (G_is_initialized(&initialized))
  194. return;
  195. init_gdal();
  196. (*pGDALAllRegister) ();
  197. G_initialize_done(&initialized);
  198. #endif
  199. }
  200. /*!
  201. \brief Get GDAL link settings for given raster map
  202. \param name map name
  203. \param mapset name of mapset
  204. \return pointer to GDAL_link structure
  205. \return NULL if link not found
  206. */
  207. struct GDAL_link *Rast_get_gdal_link(const char *name, const char *mapset)
  208. {
  209. #ifdef GDAL_LINK
  210. GDALDatasetH data;
  211. GDALRasterBandH band;
  212. GDALDataType type;
  213. RASTER_MAP_TYPE req_type;
  214. #endif
  215. const char *filename;
  216. int band_num;
  217. struct GDAL_link *gdal;
  218. RASTER_MAP_TYPE map_type;
  219. FILE *fp;
  220. struct Key_Value *key_val;
  221. const char *p;
  222. DCELL null_val;
  223. int hflip, vflip;
  224. if (!G_find_raster2(name, mapset))
  225. return NULL;
  226. map_type = Rast_map_type(name, mapset);
  227. if (map_type < 0)
  228. return NULL;
  229. fp = G_fopen_old_misc("cell_misc", "gdal", name, mapset);
  230. if (!fp)
  231. return NULL;
  232. key_val = G_fread_key_value(fp);
  233. fclose(fp);
  234. if (!key_val)
  235. return NULL;
  236. filename = G_find_key_value("file", key_val);
  237. if (!filename)
  238. return NULL;
  239. p = G_find_key_value("band", key_val);
  240. if (!p)
  241. return NULL;
  242. band_num = atoi(p);
  243. if (!band_num)
  244. return NULL;
  245. p = G_find_key_value("null", key_val);
  246. if (!p)
  247. return NULL;
  248. /* atof on windows can not read "nan" and returns 0 instead */
  249. if (strcmp(p, "none") == 0 ||
  250. G_strcasecmp(p, "nan") == 0 || G_strcasecmp(p, "-nan") == 0) {
  251. Rast_set_d_null_value(&null_val, 1);
  252. }
  253. else
  254. null_val = atof(p);
  255. hflip = G_find_key_value("hflip", key_val) ? 1 : 0;
  256. vflip = G_find_key_value("vflip", key_val) ? 1 : 0;
  257. #ifdef GDAL_LINK
  258. p = G_find_key_value("type", key_val);
  259. if (!p)
  260. return NULL;
  261. type = atoi(p);
  262. switch (type) {
  263. case GDT_Byte:
  264. case GDT_Int16:
  265. case GDT_UInt16:
  266. case GDT_Int32:
  267. case GDT_UInt32:
  268. req_type = CELL_TYPE;
  269. break;
  270. case GDT_Float32:
  271. req_type = FCELL_TYPE;
  272. break;
  273. case GDT_Float64:
  274. req_type = DCELL_TYPE;
  275. break;
  276. default:
  277. return NULL;
  278. }
  279. if (req_type != map_type)
  280. return NULL;
  281. Rast_init_gdal();
  282. data = (*pGDALOpen) (filename, GA_ReadOnly);
  283. if (!data)
  284. return NULL;
  285. band = (*pGDALGetRasterBand) (data, band_num);
  286. if (!band) {
  287. (*pGDALClose) (data);
  288. return NULL;
  289. }
  290. #endif
  291. gdal = G_calloc(1, sizeof(struct GDAL_link));
  292. gdal->filename = G_store(filename);
  293. gdal->band_num = band_num;
  294. gdal->null_val = null_val;
  295. gdal->hflip = hflip;
  296. gdal->vflip = vflip;
  297. #ifdef GDAL_LINK
  298. gdal->data = data;
  299. gdal->band = band;
  300. gdal->type = type;
  301. #endif
  302. return gdal;
  303. }
  304. struct GDAL_Options
  305. {
  306. const char *dir;
  307. const char *ext;
  308. const char *format;
  309. char **options;
  310. };
  311. static struct state
  312. {
  313. int initialized;
  314. struct GDAL_Options opts;
  315. struct Key_Value *projinfo, *projunits, *projepsg;
  316. char *srswkt;
  317. } state;
  318. static struct state *st = &state;
  319. static void read_gdal_options(void)
  320. {
  321. FILE *fp;
  322. struct Key_Value *key_val;
  323. const char *p;
  324. fp = G_fopen_old("", "GDAL", G_mapset());
  325. if (!fp)
  326. G_fatal_error(_("Unable to open GDAL file"));
  327. key_val = G_fread_key_value(fp);
  328. fclose(fp);
  329. p = G_find_key_value("directory", key_val);
  330. if (!p)
  331. p = "gdal";
  332. if (*p == '/') {
  333. st->opts.dir = G_store(p);
  334. }
  335. else {
  336. char path[GPATH_MAX];
  337. G_file_name(path, p, "", G_mapset());
  338. st->opts.dir = G_store(path);
  339. if (access(path, 0) != 0)
  340. G_make_mapset_element(p);
  341. }
  342. p = G_find_key_value("extension", key_val);
  343. st->opts.ext = G_store(p ? p : "");
  344. p = G_find_key_value("format", key_val);
  345. st->opts.format = G_store(p ? p : "GTiff");
  346. p = G_find_key_value("options", key_val);
  347. st->opts.options = p ? G_tokenize(p, ",") : NULL;
  348. G_free_key_value(key_val);
  349. }
  350. /*!
  351. \brief Create GDAL settings for given raster map
  352. \param name map name
  353. \param map_type map type (CELL, FCELL, DCELL)
  354. \return pointer to allocated GDAL_link structure
  355. \return NULL on error
  356. */
  357. struct GDAL_link *Rast_create_gdal_link(const char *name,
  358. RASTER_MAP_TYPE map_type)
  359. {
  360. #ifdef GDAL_LINK
  361. char path[GPATH_MAX];
  362. GDALDriverH driver;
  363. double transform[6];
  364. struct GDAL_link *gdal;
  365. FILE *fp;
  366. struct Key_Value *key_val;
  367. char buf[32];
  368. Rast__init_window();
  369. Rast_init_gdal();
  370. if (!G_is_initialized(&st->initialized)) {
  371. read_gdal_options();
  372. st->projinfo = G_get_projinfo();
  373. st->projunits = G_get_projunits();
  374. st->projepsg = G_get_projepsg();
  375. if (st->projinfo && st->projunits)
  376. st->srswkt = GPJ_grass_to_wkt2(st->projinfo, st->projunits,
  377. st->projepsg, 0, 0);
  378. G_initialize_done(&st->initialized);
  379. }
  380. gdal = G_calloc(1, sizeof(struct GDAL_link));
  381. sprintf(path, "%s/%s%s", st->opts.dir, name, st->opts.ext);
  382. gdal->filename = G_store(path);
  383. gdal->band_num = 1;
  384. gdal->hflip = 0;
  385. gdal->vflip = 0;
  386. switch (map_type) {
  387. case CELL_TYPE:
  388. switch (R__.nbytes) {
  389. case 1:
  390. gdal->type = GDT_Byte;
  391. gdal->null_val = (DCELL) 0xFF;
  392. break;
  393. case 2:
  394. gdal->type = GDT_UInt16;
  395. gdal->null_val = (DCELL) 0xFFFF;
  396. break;
  397. case 3:
  398. case 4:
  399. gdal->type = GDT_Int32;
  400. gdal->null_val = (DCELL) 0x80000000U;
  401. break;
  402. }
  403. break;
  404. case FCELL_TYPE:
  405. gdal->type = GDT_Float32;
  406. Rast_set_d_null_value(&gdal->null_val, 1);
  407. break;
  408. case DCELL_TYPE:
  409. gdal->type = GDT_Float64;
  410. Rast_set_d_null_value(&gdal->null_val, 1);
  411. break;
  412. default:
  413. G_fatal_error(_("Invalid map type <%d>"), map_type);
  414. break;
  415. }
  416. driver = (*pGDALGetDriverByName) (st->opts.format);
  417. if (!driver)
  418. G_fatal_error(_("Unable to get <%s> driver"), st->opts.format);
  419. /* Does driver support GDALCreate ? */
  420. if ((*pGDALGetMetadataItem) (driver, GDAL_DCAP_CREATE, NULL)) {
  421. gdal->data =
  422. (*pGDALCreate)(driver, gdal->filename,
  423. R__.wr_window.cols, R__.wr_window.rows,
  424. 1, gdal->type, st->opts.options);
  425. if (!gdal->data)
  426. G_fatal_error(_("Unable to create <%s> dataset using <%s> driver"),
  427. name, st->opts.format);
  428. }
  429. /* If not - create MEM driver for intermediate dataset.
  430. * Check if raster can be created at all (with GDALCreateCopy) */
  431. else if ((*pGDALGetMetadataItem) (driver, GDAL_DCAP_CREATECOPY, NULL)) {
  432. GDALDriverH mem_driver;
  433. G_message(_("Driver <%s> does not support direct writing. "
  434. "Using MEM driver for intermediate dataset."),
  435. st->opts.format);
  436. mem_driver = (*pGDALGetDriverByName) ("MEM");
  437. if (!mem_driver)
  438. G_fatal_error(_("Unable to get in-memory raster driver"));
  439. gdal->data =
  440. (*pGDALCreate)(mem_driver, "",
  441. R__.wr_window.cols, R__.wr_window.rows,
  442. 1, gdal->type, st->opts.options);
  443. if (!gdal->data)
  444. G_fatal_error(_("Unable to create <%s> dataset using memory driver"),
  445. name);
  446. }
  447. else
  448. G_fatal_error(_("Driver <%s> does not support creating rasters"),
  449. st->opts.format);
  450. gdal->band = (*pGDALGetRasterBand) (gdal->data, gdal->band_num);
  451. (*pGDALSetRasterNoDataValue) (gdal->band, gdal->null_val);
  452. /* Set Geo Transform */
  453. transform[0] = R__.wr_window.west;
  454. transform[1] = R__.wr_window.ew_res;
  455. transform[2] = 0.0;
  456. transform[3] = R__.wr_window.north;
  457. transform[4] = 0.0;
  458. transform[5] = -R__.wr_window.ns_res;
  459. if ((*pGDALSetGeoTransform) (gdal->data, transform) >= CE_Failure)
  460. G_warning(_("Unable to set geo transform"));
  461. if (st->srswkt)
  462. if ((*pGDALSetProjection) (gdal->data, st->srswkt) == CE_Failure)
  463. G_warning(_("Unable to set projection"));
  464. fp = G_fopen_new_misc("cell_misc", "gdal", name);
  465. if (!fp)
  466. G_fatal_error(_("Unable to create cell_misc/%s/gdal file"), name);
  467. key_val = G_create_key_value();
  468. G_set_key_value("file", gdal->filename, key_val);
  469. sprintf(buf, "%d", gdal->band_num);
  470. G_set_key_value("band", buf, key_val);
  471. sprintf(buf, "%.22g", gdal->null_val);
  472. G_set_key_value("null", buf, key_val);
  473. sprintf(buf, "%d", gdal->type);
  474. G_set_key_value("type", buf, key_val);
  475. if (G_fwrite_key_value(fp, key_val) < 0)
  476. G_fatal_error(_("Error writing cell_misc/%s/gdal file"), name);
  477. G_free_key_value(key_val);
  478. fclose(fp);
  479. return gdal;
  480. #else
  481. return NULL;
  482. #endif
  483. }
  484. /*!
  485. \brief Close existing GDAL link
  486. \param gdal pointer to GDAL_link to be closed
  487. */
  488. void Rast_close_gdal_link(struct GDAL_link *gdal)
  489. {
  490. #ifdef GDAL_LINK
  491. (*pGDALClose) (gdal->data);
  492. #endif
  493. G_free(gdal->filename);
  494. G_free(gdal);
  495. }
  496. /*!
  497. \brief Close existing GDAL link and write out data
  498. \param gdal pointer to GDAL_link to be closed
  499. \return 1 on success
  500. \return -1 on failure
  501. */
  502. int Rast_close_gdal_write_link(struct GDAL_link *gdal)
  503. {
  504. int stat = 1;
  505. #ifdef GDAL_LINK
  506. GDALDriverH src_drv = (*pGDALGetDatasetDriver) (gdal->data);
  507. if (G_strcasecmp((*pGDALGetDriverShortName) (src_drv), "MEM") == 0) {
  508. GDALDriverH dst_drv = (*pGDALGetDriverByName) (st->opts.format);
  509. GDALDatasetH dst =
  510. (*pGDALCreateCopy) (dst_drv, gdal->filename, gdal->data, FALSE,
  511. st->opts.options, NULL, NULL);
  512. if (!dst) {
  513. G_warning(_("Unable to create output file <%s> using driver <%s>"),
  514. gdal->filename, st->opts.format);
  515. stat = -1;
  516. }
  517. (*pGDALClose) (dst);
  518. }
  519. (*pGDALClose) (gdal->data);
  520. #endif
  521. G_free(gdal->filename);
  522. G_free(gdal);
  523. return stat;
  524. }
  525. #ifdef GDAL_LINK
  526. /*!
  527. \brief Input/output function for GDAL links
  528. See GDAL's RasterIO for details.
  529. */
  530. CPLErr Rast_gdal_raster_IO(GDALRasterBandH band, GDALRWFlag rw_flag,
  531. int x_off, int y_off, int x_size, int y_size,
  532. void *buffer, int buf_x_size, int buf_y_size,
  533. GDALDataType buf_type, int pixel_size,
  534. int line_size)
  535. {
  536. return (*pGDALRasterIO) (band, rw_flag, x_off, y_off, x_size, y_size,
  537. buffer, buf_x_size, buf_y_size, buf_type,
  538. pixel_size, line_size);
  539. }
  540. #endif