gdal.c 16 KB

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