30 #include "ogr_srs_api.h"
35 static const char *label =
"ERROR: ";
36 char newfmt[1024] = {0};
37 snprintf(newfmt, 1024,
"%s%s\n", label,
fmt);
39 vfprintf(stderr, newfmt, ap);
45 static const char *label =
"WARNING: ";
46 char newfmt[1024] = {0};
47 snprintf(newfmt, 1024,
"%s%s\n", label,
fmt);
49 vfprintf(stderr, newfmt, ap);
55 static const char *label =
"INFO: ";
56 char newfmt[1024] = {0};
57 snprintf(newfmt, 1024,
"%s%s\n", label,
fmt);
59 vfprintf(stderr, newfmt, ap);
79 for (i = 0; i < nbands; i++) {
81 if (
band == NULL)
continue;
98 *len = (
uint32_t) ((abs(max - min) + 1 + (step / 2)) / step);
99 *range =
rtalloc(
sizeof(
int) * *len);
102 for (i = min, j = 0; i <= max; i += step, j++)
105 else if (max < min) {
106 if (step > 0) step *= -1;
107 for (i = min, j = 0; i >= max; i += step, j++)
110 else if (min == max) {
143 const char *oldstr,
const char *newstr,
146 const char *tmp = str;
150 int oldlen = strlen(oldstr);
151 int newlen = strlen(newstr);
155 while ((tmp = strstr(tmp, oldstr)) != NULL && found != limit)
156 found++, tmp += oldlen;
158 length = strlen(str) + found * (newlen - oldlen);
159 if ((result = (
char *)
rtalloc(length + 1)) == NULL) {
160 rterror(
_(
"strreplace: Not enough memory"));
169 while ((limit-- > 0) && (tmp = strstr(tmp, oldstr)) != NULL) {
170 length = (tmp - str);
171 strncpy(result + reslen, str, length);
172 strcpy(result + (reslen += length), newstr);
178 strcpy(result + reslen, str);
189 for (j = strlen(str) - 1; j >= 0; j--)
190 str[j] = tolower(str[j]);
207 tmp =
rtalloc(
sizeof(
char) * (strlen(str) + 1));
209 rterror(
_(
"strsplit: Not enough memory"));
214 if (!strlen(tmp) || !delimiter || !strlen(delimiter)) {
216 rtn = (
char **)
rtalloc(*n *
sizeof(
char *));
218 rterror(
_(
"strsplit: Not enough memory"));
221 rtn[0] = (
char *)
rtalloc(
sizeof(
char) * (strlen(tmp) + 1));
222 if (NULL == rtn[0]) {
223 rterror(
_(
"strsplit: Not enough memory"));
231 token = strtok(tmp, delimiter);
232 while (token != NULL) {
234 rtn = (
char **)
rtalloc(
sizeof(
char *));
237 rtn = (
char **)
rtrealloc(rtn, (*n + 1) *
sizeof(
char *));
240 rterror(
_(
"strsplit: Not enough memory"));
245 rtn[*n] = (
char *)
rtalloc(
sizeof(
char) * (strlen(token) + 1));
246 if (NULL == rtn[*n]) {
247 rterror(
_(
"strsplit: Not enough memory"));
251 strcpy(rtn[*n], token);
254 token = strtok(NULL, delimiter);
271 return (
char *) input;
274 while (isspace(*input))
278 ptr = ((
char *) input) + strlen(input);
279 while (isspace(*--ptr))
282 len = strlen(input) - offset + 1;
283 rtn =
rtalloc(
sizeof(
char) * len);
285 rterror(
_(
"trim: Not enough memory"));
288 strncpy(rtn, input, len);
303 return (
char *) input;
306 while (strchr(remove, *input) != NULL)
310 ptr = ((
char *) input) + strlen(input);
311 while (strchr(remove, *--ptr) != NULL)
314 len = strlen(input) - offset + 1;
315 rtn =
rtalloc(
sizeof(
char) * len);
317 rterror(
_(
"chartrim: Not enough memory"));
320 strncpy(rtn, input, len);
321 rtn[strlen(input) - offset] =
'\0';
328 printf(
_(
"RELEASE: %s GDAL_VERSION=%d (r%d)\n"),
POSTGIS_LIB_VERSION, POSTGIS_GDAL_VERSION, POSTGIS_SVN_REVISION);
330 "USAGE: raster2pgsql [<options>] <raster>[ <raster>[ ...]] [[<schema>.]<table>]\n"
331 " Multiple rasters can also be specified using wildcards (*,?).\n"
344 " -s <srid> Set the SRID field. Defaults to %d. If SRID not\n"
345 " provided or is %d, raster's metadata will be checked to\n"
346 " determine an appropriate SRID.\n"
349 " -b <band> Index (1-based) of band to extract from raster. For more\n"
350 " than one band index, separate with comma (,). Ranges can be\n"
351 " defined by separating with dash (-). If unspecified, all bands\n"
352 " of raster will be extracted.\n"
355 " -t <tile size> Cut raster into tiles to be inserted one per\n"
356 " table row. <tile size> is expressed as WIDTHxHEIGHT.\n"
357 " <tile size> can also be \"auto\" to allow the loader to compute\n"
358 " an appropriate tile size using the first raster and applied to\n"
362 " -P Pad right-most and bottom-most tiles to guarantee that all tiles\n"
363 " have the same width and height.\n"
366 " -R Register the raster as an out-of-db (filesystem) raster. Provided\n"
367 " raster should have absolute path to the file\n"
370 " (-d|a|c|p) These are mutually exclusive options:\n"
371 " -d Drops the table, then recreates it and populates\n"
372 " it with current raster data.\n"
373 " -a Appends raster into current table, must be\n"
374 " exactly the same table schema.\n"
375 " -c Creates a new table and populates it, this is the\n"
376 " default if you do not specify any options.\n"
377 " -p Prepare mode, only creates the table.\n"
380 " -f <column> Specify the name of the raster column\n"
383 " -F Add a column with the filename of the raster.\n"
386 " -n <column> Specify the name of the filename column. Implies -F.\n"
389 " -l <overview factor> Create overview of the raster. For more than\n"
390 " one factor, separate with comma(,). Overview table name follows\n"
391 " the pattern o_<overview factor>_<table>. Created overview is\n"
392 " stored in the database and is not affected by -R.\n"
395 " -q Wrap PostgreSQL identifiers in quotes.\n"
398 " -I Create a GIST spatial index on the raster column. The ANALYZE\n"
399 " command will automatically be issued for the created index.\n"
402 " -M Run VACUUM ANALYZE on the table of the raster column. Most\n"
403 " useful when appending raster to existing table with -a.\n"
406 " -C Set the standard set of constraints on the raster\n"
407 " column after the rasters are loaded. Some constraints may fail\n"
408 " if one or more rasters violate the constraint.\n"
409 " -x Disable setting the max extent constraint. Only applied if\n"
410 " -C flag is also used.\n"
411 " -r Set the constraints (spatially unique and coverage tile) for\n"
412 " regular blocking. Only applied if -C flag is also used.\n"
415 " -T <tablespace> Specify the tablespace for the new table.\n"
416 " Note that indices (including the primary key) will still use\n"
417 " the default tablespace unless the -X flag is also used.\n"
420 " -X <tablespace> Specify the tablespace for the table's new index.\n"
421 " This applies to the primary key and the spatial index if\n"
422 " the -I flag is used.\n"
425 " -N <nodata> NODATA value to use on bands without a NODATA value.\n"
428 " -k Skip NODATA value checks for each raster band.\n"
431 " -E <endian> Control endianness of generated binary output of\n"
432 " raster. Use 0 for XDR and 1 for NDR (default). Only NDR\n"
433 " is supported at this time.\n"
436 " -V <version> Specify version of output WKB format. Default\n"
437 " is 0. Only 0 is supported at this time.\n"
440 " -e Execute each statement individually, do not use a transaction.\n"
443 " -Y Use COPY statements instead of INSERT statements.\n"
446 " -G Print the supported GDAL raster formats.\n"
449 " -? Display this help screen.\n"
453 static void calc_tile_size(
455 int *tileX,
int *tileY
469 for (j = 0; j < 2; j++) {
474 if (j < 1 && dimX <= max) {
478 else if (dimY <= max) {
483 for (i = max; i >= min; i--) {
486 r = (double) dimX / (
double) i;
491 r = (double) dimY / (
double) i;
524 memset(info->
gt, 0,
sizeof(
double) * 6);
525 memset(info->
tile_size, 0,
sizeof(
int) * 2);
530 if (info->
srs != NULL)
546 if (src->
srs != NULL) {
548 if (dst->
srs == NULL) {
549 rterror(
_(
"copy_rastinfo: Not enough memory"));
552 strcpy(dst->
srs, src->
srs);
558 if (dst->
nband == NULL) {
559 rterror(
_(
"copy_rastinfo: Not enough memory"));
567 rterror(
_(
"copy_rastinfo: Not enough memory"));
575 rterror(
_(
"copy_rastinfo: Not enough memory"));
583 rterror(
_(
"copy_rastinfo: Not enough memory"));
591 rterror(
_(
"copy_rastinfo: Not enough memory"));
596 memcpy(dst->
gt, src->
gt,
sizeof(
double) * 6);
612 rtwarn(
_(
"Different number of bands found in the set of rasters being converted to PostGIS raster"));
619 if (
x->bandtype[i] != ref->
bandtype[i]) {
620 rtwarn(
_(
"Different pixel types found for band %d in the set of rasters being converted to PostGIS raster"), ref->
nband[i]);
630 rtwarn(
_(
"Different hasnodata flags found for band %d in the set of rasters being converted to PostGIS raster"), ref->
nband[i]);
639 if (!
x->hasnodata[i] && !ref->
hasnodata[i])
continue;
641 rtwarn(
_(
"Different NODATA values found for band %d in the set of rasters being converted to PostGIS raster"), ref->
nband[i]);
658 rterror(
_(
"diff_rastinfo: Could not allocate memory for raster alignment test"));
671 rterror(
_(
"diff_rastinfo: Could not run raster alignment test"));
676 rtwarn(
_(
"Raster with different alignment found in the set of rasters being converted to PostGIS raster"));
683 for (i = 0; i < 2; i++) {
685 rtwarn(
_(
"Different tile sizes found in the set of rasters being converted to PostGIS raster"));
699 config->
table = NULL;
708 config->
nband = NULL;
710 memset(config->
tile_size, 0,
sizeof(
int) * 2);
743 if (config->
schema != NULL)
745 if (config->
table != NULL)
780 for (i = 0; i <
buffer->length; i++) {
781 if (
buffer->line[i] != NULL)
797 for (i = 0; i <
buffer->length; i++) {
798 printf(
"%s\n",
buffer->line[i]);
804 dump_stringbuffer(
buffer);
805 rtdealloc_stringbuffer(
buffer, 0);
814 if (
buffer->line == NULL) {
815 rterror(
_(
"append_stringbuffer: Could not allocate memory for appending string to buffer"));
827 flush_stringbuffer(
buffer);
829 return append_stringbuffer(
buffer, str);
833 copy_from(
const char *schema,
const char *table,
const char *column,
834 const char *filename,
const char *file_column_name,
840 assert(table != NULL);
841 assert(column != NULL);
843 len = strlen(
"COPY () FROM stdin;") + 1;
845 len += strlen(schema);
846 len += strlen(table);
847 len += strlen(column);
848 if (filename != NULL)
849 len += strlen(
",") + strlen(file_column_name);
853 rterror(
_(
"copy_from: Could not allocate memory for COPY statement"));
856 sprintf(
sql,
"COPY %s%s (%s%s%s) FROM stdin;",
857 (schema != NULL ? schema :
""),
860 (filename != NULL ?
"," :
""),
861 (filename != NULL ? file_column_name :
"")
874 append_sql_to_buffer(
buffer, strdup(
"\\."));
881 const char *schema,
const char *table,
const char *column,
882 const char *filename,
const char *file_column_name,
883 int copy_statements,
int out_srid,
891 assert(table != NULL);
892 assert(column != NULL);
895 if (copy_statements) {
898 schema, table, column,
899 (file_column_name ? filename : NULL), file_column_name,
902 rterror(
_(
"insert_records: Could not add COPY statement to string buffer"));
908 if (filename != NULL)
913 len = strlen(tileset->
line[
x]) + 1;
915 if (filename != NULL)
916 len += strlen(fn) + 1;
920 rterror(
_(
"insert_records: Could not allocate memory for COPY statement"));
923 sprintf(
sql,
"%s%s%s",
925 (filename != NULL ?
"\t" :
""),
926 (filename != NULL ? fn :
"")
933 if (!copy_from_end(
buffer)) {
934 rterror(
_(
"process_rasters: Could not add COPY end statement to string buffer"));
941 len = strlen(
"INSERT INTO () VALUES (ST_Transform(''::raster,xxxxxxxxx));") + 1;
943 len += strlen(schema);
944 len += strlen(table);
945 len += strlen(column);
946 if (filename != NULL)
947 len += strlen(
",") + strlen(file_column_name);
950 if (filename != NULL)
957 sqllen += strlen(tileset->
line[
x]);
958 if (filename != NULL)
959 sqllen += strlen(
",''") + strlen(fn);
963 rterror(
_(
"insert_records: Could not allocate memory for INSERT statement"));
967 ptr += sprintf(
sql,
"INSERT INTO %s%s (%s%s%s) VALUES (",
968 (schema != NULL ? schema :
""),
971 (filename != NULL ?
"," :
""),
972 (filename != NULL ? file_column_name :
"")
975 ptr += sprintf(ptr,
"ST_Transform(");
977 ptr += sprintf(ptr,
"'%s'::raster",
981 ptr += sprintf(ptr,
", %d)", out_srid);
983 if (filename != NULL) {
984 ptr += sprintf(ptr,
",'%s'", fn);
986 ptr += sprintf(ptr,
");");
1002 len = strlen(
"DROP TABLE IF EXISTS ;") + 1;
1004 len += strlen(schema);
1005 len += strlen(table);
1009 rterror(
_(
"drop_table: Could not allocate memory for DROP TABLE statement"));
1012 sprintf(
sql,
"DROP TABLE IF EXISTS %s%s;",
1013 (schema != NULL ? schema :
""),
1024 const char *schema,
const char *table,
const char *column,
1025 const int file_column,
const char *file_column_name,
1026 const char *tablespace,
const char *idx_tablespace,
1032 assert(table != NULL);
1033 assert(column != NULL);
1035 len = strlen(
"CREATE TABLE (\"rid\" serial PRIMARY KEY, raster);") + 1;
1037 len += strlen(schema);
1038 len += strlen(table);
1039 len += strlen(column);
1041 len += strlen(
", text") + strlen(file_column_name);
1042 if (tablespace != NULL)
1043 len += strlen(
" TABLESPACE ") + strlen(tablespace);
1044 if (idx_tablespace != NULL)
1045 len += strlen(
" USING INDEX TABLESPACE ") + strlen(idx_tablespace);
1049 rterror(
_(
"create_table: Could not allocate memory for CREATE TABLE statement"));
1052 sprintf(
sql,
"CREATE TABLE %s%s (\"rid\" serial PRIMARY KEY%s%s,%s raster%s%s%s)%s%s;",
1053 (schema != NULL ? schema :
""),
1055 (idx_tablespace != NULL ?
" USING INDEX TABLESPACE " :
""),
1056 (idx_tablespace != NULL ? idx_tablespace :
""),
1058 (file_column ?
"," :
""),
1059 (file_column ? file_column_name :
""),
1060 (file_column ?
" text" :
""),
1061 (tablespace != NULL ?
" TABLESPACE " :
""),
1062 (tablespace != NULL ? tablespace :
"")
1072 const char *schema,
const char *table,
const char *column,
1073 const char *tablespace,
1078 char *_table = NULL;
1079 char *_column = NULL;
1081 assert(table != NULL);
1082 assert(column != NULL);
1088 len = strlen(
"CREATE INDEX \"__gist\" ON USING gist (st_convexhull());") + 1;
1090 len += strlen(schema);
1091 len += strlen(_table);
1092 len += strlen(_column);
1093 len += strlen(table);
1094 len += strlen(column);
1095 if (tablespace != NULL)
1096 len += strlen(
" TABLESPACE ") + strlen(tablespace);
1100 rterror(
_(
"create_index: Could not allocate memory for CREATE INDEX statement"));
1105 sprintf(
sql,
"CREATE INDEX ON %s%s USING gist (st_convexhull(%s))%s%s;",
1106 (schema != NULL ? schema :
""),
1109 (tablespace != NULL ?
" TABLESPACE " :
""),
1110 (tablespace != NULL ? tablespace :
"")
1122 const char *schema,
const char *table,
1128 assert(table != NULL);
1130 len = strlen(
"ANALYZE ;") + 1;
1132 len += strlen(schema);
1133 len += strlen(table);
1137 rterror(
_(
"analyze_table: Could not allocate memory for ANALYZE TABLE statement"));
1140 sprintf(
sql,
"ANALYZE %s%s;",
1141 (schema != NULL ? schema :
""),
1152 const char *schema,
const char *table,
1158 assert(table != NULL);
1160 len = strlen(
"VACUUM ANALYZE ;") + 1;
1162 len += strlen(schema);
1163 len += strlen(table);
1167 rterror(
_(
"vacuum_table: Could not allocate memory for VACUUM statement"));
1170 sprintf(
sql,
"VACUUM ANALYZE %s%s;",
1171 (schema != NULL ? schema :
""),
1181 add_raster_constraints(
1182 const char *schema,
const char *table,
const char *column,
1183 int regular_blocking,
int max_extent,
1190 char *_schema = NULL;
1191 char *_table = NULL;
1192 char *_column = NULL;
1194 assert(table != NULL);
1195 assert(column != NULL);
1198 if (schema != NULL) {
1217 len = strlen(
"SELECT AddRasterConstraints('','','',TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,TRUE,TRUE,FALSE);") + 1;
1218 if (_schema != NULL)
1219 len += strlen(_schema);
1220 len += strlen(_table);
1221 len += strlen(_column);
1225 rterror(
_(
"add_raster_constraints: Could not allocate memory for AddRasterConstraints statement"));
1228 sprintf(
sql,
"SELECT AddRasterConstraints('%s','%s','%s',TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,%s,TRUE,TRUE,TRUE,TRUE,%s);",
1229 (_schema != NULL ? _schema :
""),
1232 (regular_blocking ?
"TRUE" :
"FALSE"),
1233 (max_extent ?
"TRUE" :
"FALSE")
1236 if (_schema != NULL)
1247 add_overview_constraints(
1248 const char *ovschema,
const char *ovtable,
const char *ovcolumn,
1249 const char *schema,
const char *table,
const char *column,
1258 char *_ovschema = NULL;
1259 char *_ovtable = NULL;
1260 char *_ovcolumn = NULL;
1262 char *_schema = NULL;
1263 char *_table = NULL;
1264 char *_column = NULL;
1266 assert(ovtable != NULL);
1267 assert(ovcolumn != NULL);
1268 assert(table != NULL);
1269 assert(column != NULL);
1273 if (ovschema != NULL) {
1277 _tmp =
strreplace(_ovschema,
"'",
"''", NULL);
1284 _ovtable =
strreplace(_tmp,
"'",
"''", NULL);
1289 _ovcolumn =
strreplace(_tmp,
"'",
"''", NULL);
1293 if (schema != NULL) {
1312 len = strlen(
"SELECT AddOverviewConstraints('','','','','','',);") + 5;
1313 if (_ovschema != NULL)
1314 len += strlen(_ovschema);
1315 len += strlen(_ovtable);
1316 len += strlen(_ovcolumn);
1317 if (_schema != NULL)
1318 len += strlen(_schema);
1319 len += strlen(_table);
1320 len += strlen(_column);
1324 rterror(
_(
"add_overview_constraints: Could not allocate memory for AddOverviewConstraints statement"));
1327 sprintf(
sql,
"SELECT AddOverviewConstraints('%s','%s','%s','%s','%s','%s',%d);",
1328 (_ovschema != NULL ? _ovschema :
""),
1331 (_schema != NULL ? _schema :
""),
1337 if (_ovschema != NULL)
1342 if (_schema != NULL)
1354 GDALDatasetH hdsSrc;
1356 VRTSourcedRasterBandH hbandOv;
1357 double gtOv[6] = {0.};
1362 const char *ovtable = NULL;
1365 VRTSourcedRasterBandH hbandDst;
1366 int tile_size[2] = {0};
1367 int _tile_size[2] = {0};
1368 int ntiles[2] = {1, 1};
1371 double gt[6] = {0.};
1377 hdsSrc = GDALOpenShared(config->
rt_file[idx], GA_ReadOnly);
1378 if (hdsSrc == NULL) {
1379 rterror(
_(
"build_overview: Could not open raster: %s"), config->
rt_file[idx]);
1384 memcpy(gtOv, info->
gt,
sizeof(
double) * 6);
1387 rterror(
_(
"build_overview: Invalid overview index: %d"), ovx);
1399 dimOv[0] = (int) (info->
dim[0] + (factor / 2)) / factor;
1400 dimOv[1] = (int) (info->
dim[1] + (factor / 2)) / factor;
1403 hdsOv = VRTCreate(dimOv[0], dimOv[1]);
1407 GDALSetProjection(hdsOv, info->
srs);
1413 GDALSetGeoTransform(hdsOv, gtOv);
1418 hbandOv = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsOv, j + 1);
1421 GDALSetRasterNoDataValue(hbandOv, info->
nodataval[j]);
1424 hbandOv, GDALGetRasterBand(hdsSrc, info->
nband[j]),
1426 info->
dim[0], info->
dim[1],
1429 "near", VRT_NODATA_UNSET
1434 VRTFlushCache(hdsOv);
1438 tile_size[0] = dimOv[0];
1442 tile_size[1] = dimOv[1];
1448 tile_size[0] != dimOv[0] &&
1449 tile_size[1] != dimOv[1]
1451 ntiles[0] = (dimOv[0] + tile_size[0] - 1) / tile_size[0];
1452 ntiles[1] = (dimOv[1] + tile_size[1] - 1) / tile_size[1];
1456 memcpy(
gt, gtOv,
sizeof(
double) * 6);
1460 for (ytile = 0; ytile < ntiles[1]; ytile++) {
1463 if (!config->
pad_tile && ntiles[1] > 1 && (ytile + 1) == ntiles[1])
1464 _tile_size[1] = dimOv[1] - (ytile * tile_size[1]);
1466 _tile_size[1] = tile_size[1];
1468 for (xtile = 0; xtile < ntiles[0]; xtile++) {
1475 if (!config->
pad_tile && ntiles[0] > 1 && (xtile + 1) == ntiles[0])
1476 _tile_size[0] = dimOv[0] - (xtile * tile_size[0]);
1478 _tile_size[0] = tile_size[0];
1481 GDALApplyGeoTransform(
1483 xtile * tile_size[0], ytile * tile_size[1],
1488 hdsDst = VRTCreate(_tile_size[0], _tile_size[1]);
1492 GDALSetProjection(hdsDst, info->
srs);
1493 GDALSetGeoTransform(hdsDst,
gt);
1498 hbandDst = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsDst, j + 1);
1501 GDALSetRasterNoDataValue(hbandDst, info->
nodataval[j]);
1504 hbandDst, GDALGetRasterBand(hdsOv, j + 1),
1505 xtile * tile_size[0], ytile * tile_size[1],
1506 _tile_size[0], _tile_size[1],
1508 _tile_size[0], _tile_size[1],
1509 "near", VRT_NODATA_UNSET
1514 VRTFlushCache(hdsDst);
1519 rterror(
_(
"build_overview: Could not convert VRT dataset to PostGIS raster"));
1532 rterror(
_(
"build_overview: Could not convert PostGIS raster to hex WKB"));
1538 append_stringbuffer(tileset, hex);
1543 if (tileset->
length > 10) {
1544 if (!insert_records(
1550 rterror(
_(
"build_overview: Could not convert raster tiles into INSERT or COPY statements"));
1555 rtdealloc_stringbuffer(tileset, 0);
1567 GDALDatasetH hdsSrc;
1568 GDALRasterBandH hbandSrc;
1571 int ntiles[2] = {1, 1};
1572 int _tile_size[2] = {0, 0};
1575 double gt[6] = {0.};
1576 const char* pszProjectionRef = NULL;
1587 hdsSrc = GDALOpenShared(config->
rt_file[idx], GA_ReadOnly);
1588 if (hdsSrc == NULL) {
1589 rterror(
_(
"convert_raster: Could not open raster: %s"), config->
rt_file[idx]);
1593 nband = GDALGetRasterCount(hdsSrc);
1595 rterror(
_(
"convert_raster: No bands found in raster: %s"), config->
rt_file[idx]);
1603 rterror(
_(
"convert_raster: Band %d not found in raster: %s"), config->
nband[i], config->
rt_file[idx]);
1610 pszProjectionRef = GDALGetProjectionRef(hdsSrc);
1611 if (pszProjectionRef != NULL && pszProjectionRef[0] !=
'\0') {
1612 info->
srs =
rtalloc(
sizeof(
char) * (strlen(pszProjectionRef) + 1));
1613 if (info->
srs == NULL) {
1614 rterror(
_(
"convert_raster: Could not allocate memory for storing SRS"));
1618 strcpy(info->
srs, pszProjectionRef);
1621 OGRSpatialReferenceH hSRS = OSRNewSpatialReference(NULL);
1622 if (OSRSetFromUserInput(hSRS, pszProjectionRef) == OGRERR_NONE) {
1623 const char* pszAuthorityName = OSRGetAuthorityName(hSRS, NULL);
1624 const char* pszAuthorityCode = OSRGetAuthorityCode(hSRS, NULL);
1626 pszAuthorityName != NULL &&
1627 strcmp(pszAuthorityName,
"EPSG") == 0 &&
1628 pszAuthorityCode != NULL
1630 info->
srid = atoi(pszAuthorityCode);
1633 OSRDestroySpatialReference(hSRS);
1638 rterror(
_(
"convert_raster: could not determine source srid, cannot transform to target srid %d"), config->
out_srid);
1644 if (GDALGetGeoTransform(hdsSrc, info->
gt) != CE_None) {
1645 rtinfo(
_(
"Using default geotransform matrix (0, 1, 0, 0, 0, -1) for raster: %s"), config->
rt_file[idx]);
1653 memcpy(
gt, info->
gt,
sizeof(
double) * 6);
1660 if (info->
nband == NULL) {
1661 rterror(
_(
"convert_raster: Could not allocate memory for storing band indices"));
1671 if (info->
nband == NULL) {
1672 rterror(
_(
"convert_raster: Could not allocate memory for storing band indices"));
1677 info->
nband[i] = i + 1;
1683 rterror(
_(
"convert_raster: Could not allocate memory for storing GDAL data type"));
1689 rterror(
_(
"convert_raster: Could not allocate memory for storing pixel type"));
1695 rterror(
_(
"convert_raster: Could not allocate memory for storing hasnodata flag"));
1701 rterror(
_(
"convert_raster: Could not allocate memory for storing nodata value"));
1711 info->
dim[0] = GDALGetRasterXSize(hdsSrc);
1712 info->
dim[1] = GDALGetRasterYSize(hdsSrc);
1720 info->
dim[0], info->
dim[1],
1748 hbandSrc = GDALGetRasterBand(hdsSrc, info->
nband[i]);
1751 info->
gdalbandtype[i] = GDALGetRasterDataType(hbandSrc);
1755 rterror(
_(
"convert_raster: The pixel type of band %d is a complex data type. PostGIS raster does not support complex data types"), i + 1);
1782 rtwarn(
_(
"The size of each output tile may exceed 1 GB. Use -t to specify a reasonable tile size"));
1785 if (config->
outdb) {
1789 for (ytile = 0; ytile < ntiles[1]; ytile++) {
1791 if (!config->
pad_tile && ntiles[1] > 1 && (ytile + 1) == ntiles[1])
1792 _tile_size[1] = info->
dim[1] - (ytile * info->
tile_size[1]);
1796 for (xtile = 0; xtile < ntiles[0]; xtile++) {
1799 if (!config->
pad_tile && ntiles[0] > 1 && (xtile + 1) == ntiles[0])
1800 _tile_size[0] = info->
dim[0] - (xtile * info->
tile_size[0]);
1805 GDALApplyGeoTransform(
1814 rterror(
_(
"convert_raster: Could not create raster"));
1825 _tile_size[0], _tile_size[1],
1832 rterror(
_(
"convert_raster: Could not create offline band"));
1839 rterror(
_(
"convert_raster: Could not add offlineband to raster"));
1855 rterror(
_(
"convert_raster: Could not convert PostGIS raster to hex WKB"));
1860 append_stringbuffer(tileset, hex);
1863 if (tileset->
length > 10) {
1864 if (!insert_records(
1870 rterror(
_(
"convert_raster: Could not convert raster tiles into INSERT or COPY statements"));
1874 rtdealloc_stringbuffer(tileset, 0);
1882 VRTSourcedRasterBandH hbandDst;
1885 for (ytile = 0; ytile < ntiles[1]; ytile++) {
1888 if (!config->
pad_tile && ntiles[1] > 1 && (ytile + 1) == ntiles[1])
1889 _tile_size[1] = info->
dim[1] - (ytile * info->
tile_size[1]);
1893 for (xtile = 0; xtile < ntiles[0]; xtile++) {
1900 if (!config->
pad_tile && ntiles[0] > 1 && (xtile + 1) == ntiles[0])
1901 _tile_size[0] = info->
dim[0] - (xtile * info->
tile_size[0]);
1906 GDALApplyGeoTransform(
1919 hdsDst = VRTCreate(_tile_size[0], _tile_size[1]);
1923 GDALSetProjection(hdsDst, info->
srs);
1924 GDALSetGeoTransform(hdsDst,
gt);
1929 hbandDst = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsDst, i + 1);
1932 GDALSetRasterNoDataValue(hbandDst, info->
nodataval[i]);
1935 hbandDst, GDALGetRasterBand(hdsSrc, info->
nband[i]),
1937 _tile_size[0], _tile_size[1],
1939 _tile_size[0], _tile_size[1],
1940 "near", VRT_NODATA_UNSET
1945 VRTFlushCache(hdsDst);
1950 rterror(
_(
"convert_raster: Could not convert VRT dataset to PostGIS raster"));
1960 for (i = 0; i < numbands; i++) {
1971 rterror(
_(
"convert_raster: Could not convert PostGIS raster to hex WKB"));
1977 append_stringbuffer(tileset, hex);
1982 if (tileset->
length > 10) {
1983 if (!insert_records(
1989 rterror(
_(
"convert_raster: Could not convert raster tiles into INSERT or COPY statements"));
1994 rtdealloc_stringbuffer(tileset, 0);
2009 assert(config != NULL);
2010 assert(config->
table != NULL);
2014 if (!append_sql_to_buffer(
buffer, strdup(
"BEGIN;"))) {
2015 rterror(
_(
"process_rasters: Could not add BEGIN statement to string buffer"));
2021 if (config->
opt ==
'd') {
2023 rterror(
_(
"process_rasters: Could not add DROP TABLE statement to string buffer"));
2030 rterror(
_(
"process_rasters: Could not add an overview's DROP TABLE statement to string buffer"));
2038 if (config->
opt !=
'a') {
2045 rterror(
_(
"process_rasters: Could not add CREATE TABLE statement to string buffer"));
2057 rterror(
_(
"process_rasters: Could not add an overview's CREATE TABLE statement to string buffer"));
2065 if (config->
opt !=
'p') {
2067 init_rastinfo(&refinfo);
2076 init_rastinfo(&rastinfo);
2077 init_stringbuffer(&tileset);
2080 if (!convert_raster(i, config, &rastinfo, &tileset,
buffer)) {
2081 rterror(
_(
"process_rasters: Could not process raster: %s"), config->
rt_file[i]);
2082 rtdealloc_rastinfo(&rastinfo);
2083 rtdealloc_stringbuffer(&tileset, 0);
2088 if (tileset.
length && !insert_records(
2095 rterror(
_(
"process_rasters: Could not convert raster tiles into INSERT or COPY statements"));
2096 rtdealloc_rastinfo(&rastinfo);
2097 rtdealloc_stringbuffer(&tileset, 0);
2101 rtdealloc_stringbuffer(&tileset, 0);
2104 flush_stringbuffer(
buffer);
2112 if (!build_overview(i, config, &rastinfo, j, &tileset,
buffer)) {
2113 rterror(
_(
"process_rasters: Could not create overview of factor %d for raster %s"), config->
overview[j], config->
rt_file[i]);
2114 rtdealloc_rastinfo(&rastinfo);
2115 rtdealloc_stringbuffer(&tileset, 0);
2119 if (tileset.
length && !insert_records(
2125 rterror(
_(
"process_rasters: Could not convert overview tiles into INSERT or COPY statements"));
2126 rtdealloc_rastinfo(&rastinfo);
2127 rtdealloc_stringbuffer(&tileset, 0);
2131 rtdealloc_stringbuffer(&tileset, 0);
2134 flush_stringbuffer(
buffer);
2140 copy_rastinfo(&refinfo, &rastinfo);
2142 diff_rastinfo(&rastinfo, &refinfo);
2146 rtdealloc_rastinfo(&rastinfo);
2149 rtdealloc_rastinfo(&refinfo);
2160 rterror(
_(
"process_rasters: Could not add CREATE INDEX statement to string buffer"));
2165 if (config->
opt !=
'p') {
2170 rterror(
_(
"process_rasters: Could not add ANALYZE statement to string buffer"));
2183 rterror(
_(
"process_rasters: Could not add an overview's CREATE INDEX statement to string buffer"));
2188 if (config->
opt !=
'p') {
2193 rterror(
_(
"process_rasters: Could not add an overview's ANALYZE statement to string buffer"));
2203 if (!add_raster_constraints(
2208 rterror(
_(
"process:rasters: Could not add AddRasterConstraints statement to string buffer"));
2214 if (!add_raster_constraints(
2219 rterror(
_(
"process_rasters: Could not add an overview's AddRasterConstraints statement to string buffer"));
2229 if (!add_overview_constraints(
2235 rterror(
_(
"process_rasters: Could not add an overview's AddOverviewConstraints statement to string buffer"));
2242 if (!append_sql_to_buffer(
buffer, strdup(
"END;"))) {
2243 rterror(
_(
"process_rasters: Could not add END statement to string buffer"));
2254 rterror(
_(
"process_rasters: Could not add VACUUM statement to string buffer"));
2264 rterror(
_(
"process_rasters: Could not add an overview's VACUUM statement to string buffer"));
2276 main(
int argc,
char **argv) {
2281 char **elements = NULL;
2283 GDALDriverH drv = NULL;
2290 setlocale (LC_ALL,
"");
2291 bindtextdomain (PACKAGE, LOCALEDIR);
2292 textdomain (PACKAGE);
2303 if (config == NULL) {
2304 rterror(
_(
"Could not allocate memory for loader configuration"));
2307 init_config(config);
2313 for (argit = 1; argit < argc; argit++) {
2317 if (
CSEQUAL(argv[argit],
"-s") && argit < argc - 1) {
2318 optarg = argv[++argit];
2319 ptr = strchr(optarg,
':');
2322 sscanf(optarg,
"%d", &config->
srid);
2323 sscanf(ptr,
"%d", &config->
out_srid);
2325 config->
srid = atoi(optarg);
2329 else if (
CSEQUAL(argv[argit],
"-b") && argit < argc - 1) {
2330 elements =
strsplit(argv[++argit],
",", &n);
2332 rterror(
_(
"Could not process -b"));
2333 rtdealloc_config(config);
2338 for (j = 0; j < n; j++) {
2339 char *t =
trim(elements[j]);
2340 char **minmax = NULL;
2350 if (!
array_range(atoi(minmax[0]), atoi(minmax[1]), 1, &range, &p)) {
2351 rterror(
_(
"Could not allocate memory for storing band indices"));
2352 for (l = 0; l < o; l++)
2355 for (j = 0; j < n; j++)
2359 rtdealloc_config(config);
2366 if (range == NULL) {
2367 rterror(
_(
"Could not allocate memory for storing band indices"));
2368 for (l = 0; l < o; l++)
2371 for (j = 0; j < n; j++)
2375 rtdealloc_config(config);
2384 if (config->
nband == NULL) {
2385 rterror(
_(
"Could not allocate memory for storing band indices"));
2387 for (l = 0; l < o; l++)
2390 for (j = 0; j < n; j++)
2394 rtdealloc_config(config);
2398 for (l = 0; l < p; l++, m++)
2399 config->
nband[m] = range[l];
2403 for (l = 0; l < o; l++)
2415 if (config->
nband[j] < 1) {
2416 rterror(
_(
"Band index %d must be greater than 0"), config->
nband[j]);
2417 rtdealloc_config(config);
2423 else if (
CSEQUAL(argv[argit],
"-t") && argit < argc - 1) {
2424 if (
CSEQUAL(argv[++argit],
"auto")) {
2429 elements =
strsplit(argv[argit],
"x", &n);
2431 rterror(
_(
"Could not process -t"));
2432 rtdealloc_config(config);
2436 for (j = 0; j < n; j++) {
2437 char *t =
trim(elements[j]);
2446 for (j = 0; j < 2; j++) {
2448 rterror(
_(
"Tile size must be greater than 0x0"));
2449 rtdealloc_config(config);
2456 else if (
CSEQUAL(argv[argit],
"-P")) {
2460 else if (
CSEQUAL(argv[argit],
"-R")) {
2464 else if (
CSEQUAL(argv[argit],
"-d")) {
2468 else if (
CSEQUAL(argv[argit],
"-a")) {
2472 else if (
CSEQUAL(argv[argit],
"-c")) {
2476 else if (
CSEQUAL(argv[argit],
"-p")) {
2480 else if (
CSEQUAL(argv[argit],
"-f") && argit < argc - 1) {
2481 const size_t len = (strlen(argv[++argit]) + 1);
2484 rterror(
_(
"Could not allocate memory for storing raster column name"));
2485 rtdealloc_config(config);
2491 else if (
CSEQUAL(argv[argit],
"-F")) {
2495 else if (
CSEQUAL(argv[argit],
"-n") && argit < argc - 1) {
2496 const size_t len = (strlen(argv[++argit]) + 1);
2499 rterror(
_(
"Could not allocate memory for storing filename column name"));
2500 rtdealloc_config(config);
2507 else if (
CSEQUAL(argv[argit],
"-l") && argit < argc - 1) {
2508 elements =
strsplit(argv[++argit],
",", &n);
2510 rterror(
_(
"Could not process -l"));
2511 rtdealloc_config(config);
2518 rterror(
_(
"Could not allocate memory for storing overview factors"));
2519 rtdealloc_config(config);
2522 for (j = 0; j < n; j++) {
2523 char *t =
trim(elements[j]);
2535 rtdealloc_config(config);
2541 else if (
CSEQUAL(argv[argit],
"-q")) {
2545 else if (
CSEQUAL(argv[argit],
"-I")) {
2549 else if (
CSEQUAL(argv[argit],
"-M")) {
2553 else if (
CSEQUAL(argv[argit],
"-C")) {
2557 else if (
CSEQUAL(argv[argit],
"-x")) {
2561 else if (
CSEQUAL(argv[argit],
"-r")) {
2565 else if (
CSEQUAL(argv[argit],
"-T") && argit < argc - 1) {
2566 const size_t len = (strlen(argv[++argit]) + 1);
2569 rterror(
_(
"Could not allocate memory for storing tablespace of new table"));
2570 rtdealloc_config(config);
2573 strncpy(config->
tablespace, argv[argit], len);
2576 else if (
CSEQUAL(argv[argit],
"-X") && argit < argc - 1) {
2577 const size_t len = (strlen(argv[++argit]) + 1);
2580 rterror(
_(
"Could not allocate memory for storing tablespace of new indices"));
2581 rtdealloc_config(config);
2587 else if (
CSEQUAL(argv[argit],
"-N") && argit < argc - 1) {
2589 config->
nodataval = atof(argv[++argit]);
2592 else if (
CSEQUAL(argv[argit],
"-k")) {
2596 else if (
CSEQUAL(argv[argit],
"-E") && argit < argc - 1) {
2597 config->
endian = atoi(argv[++argit]);
2601 else if (
CSEQUAL(argv[argit],
"-V") && argit < argc - 1) {
2602 config->
version = atoi(argv[++argit]);
2606 else if (
CSEQUAL(argv[argit],
"-e")) {
2610 else if (
CSEQUAL(argv[argit],
"-Y")) {
2614 else if (
CSEQUAL(argv[argit],
"-G")) {
2617 if (drv_set == NULL || !drv_count) {
2618 rterror(
_(
"Could not get list of available GDAL raster formats"));
2621 printf(
_(
"Supported GDAL raster formats:\n"));
2622 for (j = 0; j < drv_count; j++) {
2623 printf(
_(
" %s\n"), drv_set[j].long_name);
2632 rtdealloc_config(config);
2636 else if (
CSEQUAL(argv[argit],
"-?")) {
2638 rtdealloc_config(config);
2645 if (config->
rt_file == NULL) {
2646 rterror(
_(
"Could not allocate memory for storing raster files"));
2647 rtdealloc_config(config);
2651 len = strlen(argv[argit]) + 1;
2654 rterror(
_(
"Could not allocate memory for storing raster filename"));
2655 rtdealloc_config(config);
2664 rterror(
_(
"Invalid argument combination - cannot use -Y with -s FROM_SRID:TO_SRID"));
2675 rtdealloc_config(config);
2692 if (config->
schema == NULL) {
2693 rterror(
_(
"Could not allocate memory for storing schema name"));
2694 rtdealloc_config(config);
2701 if (config->
table == NULL) {
2702 rterror(
_(
"Could not allocate memory for storing table name"));
2703 rtdealloc_config(config);
2713 if (config->
table == NULL) {
2714 rterror(
_(
"Could not allocate memory for storing table name"));
2715 rtdealloc_config(config);
2723 if (config->
rt_file == NULL) {
2724 rterror(
_(
"Could not reallocate the memory holding raster names"));
2725 rtdealloc_config(config);
2737 drv = GDALIdentifyDriver(config->
rt_file[i], NULL);
2741 rtdealloc_config(config);
2749 rterror(
_(
"Could not allocate memory for cleaned raster filenames"));
2750 rtdealloc_config(config);
2759 rterror(
_(
"Could not allocate memory for cleaned raster filename"));
2760 rtdealloc_config(config);
2763 strcpy(file, config->
rt_file[i]);
2765 for (ptr = file + strlen(file); ptr > file; ptr--) {
2766 if (*ptr ==
'/' || *ptr ==
'\\') {
2774 rterror(
_(
"Could not allocate memory for cleaned raster filename"));
2775 rtdealloc_config(config);
2787 if (config->
table == NULL) {
2793 rterror(
_(
"Could not allocate memory for proxy table name"));
2794 rtdealloc_config(config);
2799 for (ptr = file + strlen(file); ptr > file; ptr--) {
2806 config->
table =
rtalloc(
sizeof(
char) * (strlen(file) + 1));
2807 if (config->
table == NULL) {
2808 rterror(
_(
"Could not allocate memory for proxy table name"));
2809 rtdealloc_config(config);
2812 strcpy(config->
table, file);
2820 rterror(
_(
"Could not allocate memory for default raster column name"));
2821 rtdealloc_config(config);
2831 rterror(
_(
"Could not allocate memory for default filename column name"));
2832 rtdealloc_config(config);
2844 if (config->
schema != NULL)
2846 if (config->
table != NULL)
2866 rterror(
_(
"Could not allocate memory for overview table names"));
2867 rtdealloc_config(config);
2872 sprintf(factor,
"%d", config->
overview[i]);
2876 rterror(
_(
"Could not allocate memory for overview table name"));
2877 rtdealloc_config(config);
2889 rtwarn(
_(
"The schema name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2895 rtwarn(
_(
"The table name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2901 rtwarn(
_(
"The column name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2907 rtwarn(
_(
"The column name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2913 rtwarn(
_(
"The tablespace name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2919 rtwarn(
_(
"The index tablespace name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2927 rtwarn(
_(
"The overview table name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2939 if (config->
schema != NULL) {
2942 rterror(
_(
"Could not allocate memory for quoting schema name"));
2943 rtdealloc_config(config);
2947 sprintf(tmp,
"\"%s\".", config->
schema);
2951 if (config->
table != NULL) {
2952 tmp =
rtalloc(
sizeof(
char) * (strlen(config->
table) + 3));
2954 rterror(
_(
"Could not allocate memory for quoting table name"));
2955 rtdealloc_config(config);
2959 sprintf(tmp,
"\"%s\"", config->
table);
2961 config->
table = tmp;
2966 rterror(
_(
"Could not allocate memory for quoting raster column name"));
2967 rtdealloc_config(config);
2978 rterror(
_(
"Could not allocate memory for quoting raster column name"));
2979 rtdealloc_config(config);
2990 rterror(
_(
"Could not allocate memory for quoting tablespace name"));
2991 rtdealloc_config(config);
3002 rterror(
_(
"Could not allocate memory for quoting index tablespace name"));
3003 rtdealloc_config(config);
3015 rterror(
_(
"Could not allocate memory for quoting overview table name"));
3016 rtdealloc_config(config);
3033 rterror(
_(
"Could not allocate memory for output string buffer"));
3034 rtdealloc_config(config);
3037 init_stringbuffer(
buffer);
3040 if (!process_rasters(config,
buffer)) {
3041 rterror(
_(
"Unable to process rasters"));
3042 rtdealloc_stringbuffer(
buffer, 1);
3043 rtdealloc_config(config);
3047 flush_stringbuffer(
buffer);
3049 rtdealloc_stringbuffer(
buffer, 1);
3050 rtdealloc_config(config);
int main(int argc, char *argv[])
#define SRID_UNKNOWN
Unknown SRID value.
void * default_rt_allocator(size_t size)
The default memory/logging handlers installed by lwgeom_install_default_allocators()
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
rt_pixtype rt_util_gdal_datatype_to_pixtype(GDALDataType gdt)
Convert GDALDataType to rt_pixtype.
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
void rtinfo(const char *fmt,...)
rt_gdaldriver rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t cancc)
Returns a set of available GDAL drivers.
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
char * rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize)
Return this raster in HEXWKB form (null-terminated hex)
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
void default_rt_deallocator(void *mem)
void rtwarn(const char *fmt,...)
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
void rt_band_destroy(rt_band band)
Destroy a raster band.
void * rtrealloc(void *mem, size_t size)
uint16_t rt_raster_get_num_bands(rt_raster raster)
rt_band rt_band_new_offline(uint16_t width, uint16_t height, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, uint8_t bandNum, const char *path)
Create an out-db rt_band.
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
void rtdealloc(void *mem)
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
int rt_band_get_ownsdata_flag(rt_band band)
Return 0 (FALSE) or non-zero (TRUE) indicating if rt_band is responsible for managing the memory for ...
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
void * default_rt_reallocator(void *mem, size_t size)
void rt_set_handlers(rt_allocator allocator, rt_reallocator reallocator, rt_deallocator deallocator, rt_message_handler error_handler, rt_message_handler info_handler, rt_message_handler warning_handler)
This function is called when the PostgreSQL backend is taking care of the memory and we want to use p...
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Datum buffer(PG_FUNCTION_ARGS)
static void loader_rt_error_handler(const char *fmt, va_list ap)
static char * strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
static char ** strsplit(const char *str, const char *delimiter, uint32_t *n)
static int array_range(int min, int max, int step, int **range, uint32_t *len)
static char * chartrim(const char *input, char *remove)
static char * trim(const char *input)
static void loader_rt_info_handler(const char *fmt, va_list ap)
static void rt_init_allocators(void)
static char * strtolower(char *str)
static void raster_destroy(rt_raster raster)
static void loader_rt_warning_handler(const char *fmt, va_list ap)
#define POSTGIS_LIB_VERSION
GDALDataType * gdalbandtype