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