GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
gdal.c
Go to the documentation of this file.
1/*!
2 \file lib/raster/gdal.c
3
4 \brief Raster Library - Utilization of GDAL library.
5
6 (C) 2010 by the GRASS Development Team
7
8 This program is free software under the GNU General Public License
9 (>=v2). Read the file COPYING that comes with GRASS for details.
10
11 \author Glynn Clements
12 */
13
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17
18#include <grass/config.h>
19#include <grass/gis.h>
20#include <grass/raster.h>
21#include <grass/gprojects.h>
22#include <grass/glocale.h>
23
24#include "R.h"
25
26#include <gdal.h>
27
28/*!
29 \brief Initialization
30
31 Register all GDAL drivers.
32 */
34{
35 static int initialized;
36
37 if (G_is_initialized(&initialized))
38 return;
39
41 G_initialize_done(&initialized);
42}
43
44/*!
45 \brief Get GDAL link settings for given raster map
46
47 \param name map name
48 \param mapset name of mapset
49
50 \return pointer to GDAL_link structure
51 \return NULL if link not found
52 */
53struct GDAL_link *Rast_get_gdal_link(const char *name, const char *mapset)
54{
59 const char *filename;
60 int band_num;
61 struct GDAL_link *gdal;
62 RASTER_MAP_TYPE map_type;
63 FILE *fp;
64 struct Key_Value *key_val;
65 const char *p;
66 DCELL null_val;
67 int hflip, vflip;
68
69 if (!G_find_raster2(name, mapset))
70 return NULL;
71
72 map_type = Rast_map_type(name, mapset);
73 if (map_type < 0)
74 return NULL;
75
76 fp = G_fopen_old_misc("cell_misc", "gdal", name, mapset);
77 if (!fp)
78 return NULL;
80 fclose(fp);
81
82 if (!key_val)
83 return NULL;
84
85 filename = G_find_key_value("file", key_val);
86 if (!filename)
87 return NULL;
88
89 p = G_find_key_value("band", key_val);
90 if (!p)
91 return NULL;
92 band_num = atoi(p);
93 if (!band_num)
94 return NULL;
95
96 p = G_find_key_value("null", key_val);
97 if (!p)
98 return NULL;
99 /* atof on windows can not read "nan" and returns 0 instead */
100 if (strcmp(p, "none") == 0 || G_strcasecmp(p, "nan") == 0 ||
101 G_strcasecmp(p, "-nan") == 0) {
102 Rast_set_d_null_value(&null_val, 1);
103 }
104 else
105 null_val = atof(p);
106
107 hflip = G_find_key_value("hflip", key_val) ? 1 : 0;
108 vflip = G_find_key_value("vflip", key_val) ? 1 : 0;
109
110 p = G_find_key_value("type", key_val);
111 if (!p)
112 return NULL;
113 type = atoi(p);
114
115 switch (type) {
116 case GDT_Byte:
117 case GDT_Int8:
118 case GDT_Int16:
119 case GDT_UInt16:
120 case GDT_Int32:
121 case GDT_UInt32:
123 break;
124 case GDT_Float32:
126 break;
127 case GDT_Float64:
129 break;
130 default:
131 return NULL;
132 }
133
134 if (req_type != map_type)
135 return NULL;
136
138
139 data = GDALOpen(filename, GA_ReadOnly);
140 if (!data)
141 return NULL;
142
143 band = GDALGetRasterBand(data, band_num);
144 if (!band) {
145 GDALClose(data);
146 return NULL;
147 }
148
149 gdal = G_calloc(1, sizeof(struct GDAL_link));
150
151 gdal->filename = G_store(filename);
152 gdal->band_num = band_num;
153 gdal->null_val = null_val;
154 gdal->hflip = hflip;
155 gdal->vflip = vflip;
156 gdal->data = data;
157 gdal->band = band;
158 gdal->type = type;
159
160 return gdal;
161}
162
163struct GDAL_Options {
164 const char *dir;
165 const char *ext;
166 const char *format;
167 char **options;
168};
169
170static struct state {
171 int initialized;
172 struct GDAL_Options opts;
173 struct Key_Value *projinfo, *projunits, *projepsg;
174 char *srswkt;
175} state;
176
177static struct state *st = &state;
178
179static void read_gdal_options(void)
180{
181 FILE *fp;
182 struct Key_Value *key_val;
183 const char *p;
184
185 fp = G_fopen_old("", "GDAL", G_mapset());
186 if (!fp)
187 G_fatal_error(_("Unable to open GDAL file"));
189 fclose(fp);
190
191 p = G_find_key_value("directory", key_val);
192 if (!p)
193 p = "gdal";
194 if (*p == '/') {
195 st->opts.dir = G_store(p);
196 }
197 else {
198 char path[GPATH_MAX];
199
200 G_file_name(path, p, "", G_mapset());
201 st->opts.dir = G_store(path);
202 if (access(path, 0) != 0)
204 }
205
206 p = G_find_key_value("extension", key_val);
207 st->opts.ext = G_store(p ? p : "");
208
209 p = G_find_key_value("format", key_val);
210 st->opts.format = G_store(p ? p : "GTiff");
211
212 p = G_find_key_value("options", key_val);
213 st->opts.options = p ? G_tokenize(p, ",") : NULL;
214
216}
217
218/*!
219 \brief Create GDAL settings for given raster map
220
221 \param name map name
222 \param map_type map type (CELL, FCELL, DCELL)
223
224 \return pointer to allocated GDAL_link structure
225 \return NULL on error
226 */
228 RASTER_MAP_TYPE map_type)
229{
230 char path[GPATH_MAX];
232 double transform[6];
233 struct GDAL_link *gdal;
234 FILE *fp;
235 struct Key_Value *key_val;
236 char buf[32];
237
239
241
242 if (!G_is_initialized(&st->initialized)) {
243 read_gdal_options();
244 st->projinfo = G_get_projinfo();
245 st->projunits = G_get_projunits();
246 st->projepsg = G_get_projepsg();
247 if (st->projinfo && st->projunits)
248 st->srswkt = GPJ_grass_to_wkt2(st->projinfo, st->projunits,
249 st->projepsg, 0, 0);
250 G_initialize_done(&st->initialized);
251 }
252
253 gdal = G_calloc(1, sizeof(struct GDAL_link));
254
255 snprintf(path, sizeof(path), "%s/%s%s", st->opts.dir, name, st->opts.ext);
256 gdal->filename = G_store(path);
257 gdal->band_num = 1;
258 gdal->hflip = 0;
259 gdal->vflip = 0;
260
261 switch (map_type) {
262 case CELL_TYPE:
263 switch (R__.nbytes) {
264 case 1:
265 gdal->type = GDT_Byte;
266 gdal->null_val = (DCELL)0xFF;
267 break;
268 case 2:
269 gdal->type = GDT_UInt16;
270 gdal->null_val = (DCELL)0xFFFF;
271 break;
272 case 3:
273 case 4:
274 gdal->type = GDT_Int32;
275 gdal->null_val = (DCELL)0x80000000U;
276 break;
277 }
278 break;
279 case FCELL_TYPE:
280 gdal->type = GDT_Float32;
282 break;
283 case DCELL_TYPE:
284 gdal->type = GDT_Float64;
286 break;
287 default:
288 G_fatal_error(_("Invalid map type <%d>"), map_type);
289 break;
290 }
291
292 driver = GDALGetDriverByName(st->opts.format);
293 if (!driver)
294 G_fatal_error(_("Unable to get <%s> driver"), st->opts.format);
295
296 /* Does driver support GDALCreate ? */
298 gdal->data =
300 R__.wr_window.rows, 1, gdal->type, st->opts.options);
301 if (!gdal->data)
302 G_fatal_error(_("Unable to create <%s> dataset using <%s> driver"),
303 name, st->opts.format);
304 }
305 /* If not - create MEM driver for intermediate dataset.
306 * Check if raster can be created at all (with GDALCreateCopy) */
309
310 G_message(_("Driver <%s> does not support direct writing. "
311 "Using MEM driver for intermediate dataset."),
312 st->opts.format);
313
315 if (!mem_driver)
316 G_fatal_error(_("Unable to get in-memory raster driver"));
317
318 gdal->data =
320 1, gdal->type, st->opts.options);
321 if (!gdal->data)
323 _("Unable to create <%s> dataset using memory driver"), name);
324 }
325 else
326 G_fatal_error(_("Driver <%s> does not support creating rasters"),
327 st->opts.format);
328
329 gdal->band = GDALGetRasterBand(gdal->data, gdal->band_num);
330
332
333 /* Set Geo Transform */
334 transform[0] = R__.wr_window.west;
335 transform[1] = R__.wr_window.ew_res;
336 transform[2] = 0.0;
337 transform[3] = R__.wr_window.north;
338 transform[4] = 0.0;
339 transform[5] = -R__.wr_window.ns_res;
340
342 G_warning(_("Unable to set geo transform"));
343
344 if (st->srswkt)
345 if (GDALSetProjection(gdal->data, st->srswkt) == CE_Failure)
346 G_warning(_("Unable to set projection"));
347
348 fp = G_fopen_new_misc("cell_misc", "gdal", name);
349 if (!fp)
350 G_fatal_error(_("Unable to create cell_misc/%s/gdal file"), name);
351
353
354 G_set_key_value("file", gdal->filename, key_val);
355
356 snprintf(buf, sizeof(buf), "%d", gdal->band_num);
357 G_set_key_value("band", buf, key_val);
358
359 snprintf(buf, sizeof(buf), "%.22g", gdal->null_val);
360 G_set_key_value("null", buf, key_val);
361
362 snprintf(buf, sizeof(buf), "%d", gdal->type);
363 G_set_key_value("type", buf, key_val);
364
365 if (G_fwrite_key_value(fp, key_val) < 0)
366 G_fatal_error(_("Error writing cell_misc/%s/gdal file"), name);
367
369
370 fclose(fp);
371
372 return gdal;
373}
374
375/*!
376 \brief Close existing GDAL link
377
378 \param gdal pointer to GDAL_link to be closed
379 */
381{
382 GDALClose(gdal->data);
383 G_free(gdal->filename);
384 G_free(gdal);
385}
386
387/*!
388 \brief Close existing GDAL link and write out data
389
390 \param gdal pointer to GDAL_link to be closed
391
392 \return 1 on success
393 \return -1 on failure
394 */
396{
397 int stat = 1;
398
400
401 if (G_strcasecmp(GDALGetDriverShortName(src_drv), "MEM") == 0) {
403 GDALDatasetH dst = GDALCreateCopy(dst_drv, gdal->filename, gdal->data,
404 FALSE, st->opts.options, NULL, NULL);
405
406 if (!dst) {
407 G_warning(_("Unable to create output file <%s> using driver <%s>"),
408 gdal->filename, st->opts.format);
409 stat = -1;
410 }
411 GDALClose(dst);
412 }
413
414 GDALClose(gdal->data);
415
416 G_free(gdal->filename);
417 G_free(gdal);
418
419 return stat;
420}
421
422/*!
423 \brief Input/output function for GDAL links
424
425 See GDAL's RasterIO for details.
426 */
428 int y_off, int x_size, int y_size, void *buffer,
429 int buf_x_size, int buf_y_size,
431{
432 return GDALRasterIO(band, rw_flag, x_off, y_off, x_size, y_size, buffer,
434 line_size);
435}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
struct Key_Value * G_get_projinfo(void)
Gets projection information for location.
#define G_calloc(m, n)
Definition defs/gis.h:140
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
struct Key_Value * G_get_projepsg(void)
Gets EPSG information for the current location.
int G_fwrite_key_value(FILE *, const struct Key_Value *)
Write key/value pairs to file.
Definition key_value2.c:25
int G_make_mapset_object_group(const char *)
Create directory for group of elements of a given type.
Definition mapset_msc.c:75
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition file_name.c:61
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition gis/open.c:253
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
Definition key_value1.c:104
void G_set_key_value(const char *, const char *, struct Key_Value *)
Set value for given key.
Definition key_value1.c:39
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition gis/token.c:47
struct Key_Value * G_create_key_value(void)
Allocate and initialize Key_Value structure.
Definition key_value1.c:23
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition key_value1.c:85
struct Key_Value * G_fread_key_value(FILE *)
Read key/values pairs from file.
Definition key_value2.c:49
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition open_misc.c:210
int G_is_initialized(int *)
Definition counter.c:60
void G_initialize_done(int *)
Definition counter.c:77
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:47
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:87
void G_message(const char *,...) __attribute__((format(printf
FILE * G_fopen_new_misc(const char *, const char *, const char *)
open a new database misc file
Definition open_misc.c:183
struct Key_Value * G_get_projunits(void)
Gets units information for location.
const char * G_find_raster2(const char *, const char *)
Find a raster map (look but don't touch)
Definition find_rast.c:76
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:33
char * GPJ_grass_to_wkt2(const struct Key_Value *, const struct Key_Value *, const struct Key_Value *, int, int)
Converts a GRASS co-ordinate system representation to WKT style. EPSG code is preferred if available.
Definition convert.c:143
void Rast__init_window(void)
void Rast_set_d_null_value(DCELL *, int)
To set a number of DCELL raster values to NULL.
Definition null_val.c:153
RASTER_MAP_TYPE Rast_map_type(const char *, const char *)
Determine raster data type.
int Rast_close_gdal_write_link(struct GDAL_link *gdal)
Close existing GDAL link and write out data.
Definition gdal.c:395
struct GDAL_link * Rast_create_gdal_link(const char *name, RASTER_MAP_TYPE map_type)
Create GDAL settings for given raster map.
Definition gdal.c:227
void Rast_close_gdal_link(struct GDAL_link *gdal)
Close existing GDAL link.
Definition gdal.c:380
void Rast_init_gdal(void)
Initialization.
Definition gdal.c:33
struct GDAL_link * Rast_get_gdal_link(const char *name, const char *mapset)
Get GDAL link settings for given raster map.
Definition gdal.c:53
CPLErr Rast_gdal_raster_IO(GDALRasterBandH band, GDALRWFlag rw_flag, int x_off, int y_off, int x_size, int y_size, void *buffer, int buf_x_size, int buf_y_size, GDALDataType buf_type, int pixel_size, int line_size)
Input/output function for GDAL links.
Definition gdal.c:427
#define GPATH_MAX
Definition gis.h:199
#define FALSE
Definition gis.h:82
double DCELL
Definition gis.h:635
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
struct state state
Definition parser.c:103
struct state * st
Definition parser.c:104
#define FCELL_TYPE
Definition raster.h:12
#define DCELL_TYPE
Definition raster.h:13
#define CELL_TYPE
Definition raster.h:11
int RASTER_MAP_TYPE
Definition raster.h:25
Definition R.h:82
int nbytes
Definition R.h:87
struct Cell_head wr_window
Definition R.h:93
Definition path.h:15
#define access
Definition unistd.h:7