1046{
1048
1052
1055
1056 double scale[2] = {0};
1057 double *scale_x = NULL;
1058 double *scale_y = NULL;
1059
1060 int dim[2] = {0};
1061 int *dim_x = NULL;
1062 int *dim_y = NULL;
1063
1064 ArrayType *array;
1065 Oid etype;
1066 Datum *e;
1067 bool *nulls;
1068 int16 typlen;
1069 bool typbyval;
1070 char typalign;
1071 int n = 0;
1072 int i = 0;
1073 int j = 0;
1074 int haserr = 0;
1075
1076 text *pixeltypetext = NULL;
1077 char *pixeltype = NULL;
1080 uint32_t pixtypes_len = 0;
1081
1082 double *values = NULL;
1083 uint32_t values_len = 0;
1084
1085 uint8_t *hasnodatas = NULL;
1086 double *nodatavals = NULL;
1087 uint32_t nodatavals_len = 0;
1088
1089 double ulw[2] = {0};
1090 double *ul_xw = NULL;
1091 double *ul_yw = NULL;
1092
1093 double gridw[2] = {0};
1094 double *grid_xw = NULL;
1095 double *grid_yw = NULL;
1096
1097 double skew[2] = {0};
1098 double *skew_x = NULL;
1099 double *skew_y = NULL;
1100
1101 char **options = NULL;
1102 int options_len = 0;
1103
1104 uint32_t num_bands = 0;
1105
1107 char *srs = NULL;
1108
1110
1111
1112
1113
1114 if (PG_ARGISNULL(0))
1115 PG_RETURN_NULL();
1116
1117 gser = PG_GETARG_GSERIALIZED_P(0);
1119
1120
1124 geom = geom2d;
1125 }
1126
1127
1131 PG_FREE_IF_COPY(gser, 0);
1132
1134 if (rast == NULL)
1135 PG_RETURN_NULL();
1136
1139
1140 if (NULL == pgrast)
1141 PG_RETURN_NULL();
1142
1143 SET_VARSIZE(pgrast, pgrast->
size);
1144 PG_RETURN_POINTER(pgrast);
1145 }
1146
1147
1148 if (!PG_ARGISNULL(1)) {
1149 scale[0] = PG_GETARG_FLOAT8(1);
1151 scale_x = &scale[0];
1152 }
1153
1154
1155 if (!PG_ARGISNULL(2)) {
1156 scale[1] = PG_GETARG_FLOAT8(2);
1158 scale_y = &scale[1];
1159 }
1160 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: scale (x, y) = %f, %f", scale[0], scale[1]);
1161
1162
1163 if (!PG_ARGISNULL(3)) {
1164 dim[0] = PG_GETARG_INT32(3);
1165 if (dim[0] < 0) dim[0] = 0;
1166 if (dim[0] != 0) dim_x = &dim[0];
1167 }
1168
1169
1170 if (!PG_ARGISNULL(4)) {
1171 dim[1] = PG_GETARG_INT32(4);
1172 if (dim[1] < 0) dim[1] = 0;
1173 if (dim[1] != 0) dim_y = &dim[1];
1174 }
1176
1177
1178 if (!PG_ARGISNULL(5)) {
1179 array = PG_GETARG_ARRAYTYPE_P(5);
1180 etype = ARR_ELEMTYPE(array);
1181 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1182
1183 switch (etype) {
1184 case TEXTOID:
1185 break;
1186 default:
1187
1189 PG_FREE_IF_COPY(gser, 0);
1190
1191 elog(ERROR, "RASTER_asRaster: Invalid data type for pixeltype");
1192 PG_RETURN_NULL();
1193 break;
1194 }
1195
1196 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1197 &nulls, &n);
1198
1199 if (n) {
1201
1202 for (i = 0, j = 0; i < n; i++) {
1203 if (nulls[i]) {
1205 continue;
1206 }
1207
1208 pixeltype = NULL;
1209 switch (etype) {
1210 case TEXTOID:
1211 pixeltypetext = (text *) DatumGetPointer(e[i]);
1212 if (NULL == pixeltypetext) break;
1213 pixeltype = text_to_cstring(pixeltypetext);
1214
1215
1218 break;
1219 }
1220
1221 if (strlen(pixeltype)) {
1224
1225 pfree(pixtypes);
1226
1228 PG_FREE_IF_COPY(gser, 0);
1229
1230 elog(ERROR, "RASTER_asRaster: Invalid pixel type provided: %s", pixeltype);
1231 PG_RETURN_NULL();
1232 }
1233
1234 pixtypes[j] = pixtype;
1235 j++;
1236 }
1237 }
1238
1239 if (j > 0) {
1240
1241 pixtypes = repalloc(pixtypes, j *
sizeof(
rt_pixtype));
1242 pixtypes_len = j;
1243 }
1244 else {
1245 pfree(pixtypes);
1246 pixtypes = NULL;
1247 pixtypes_len = 0;
1248 }
1249 }
1250 }
1251#if POSTGIS_DEBUG_LEVEL > 0
1252 for (uint32_t u = 0; u < pixtypes_len; u++)
1254#endif
1255
1256
1257 if (!PG_ARGISNULL(6)) {
1258 array = PG_GETARG_ARRAYTYPE_P(6);
1259 etype = ARR_ELEMTYPE(array);
1260 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1261
1262 switch (etype) {
1263 case FLOAT4OID:
1264 case FLOAT8OID:
1265 break;
1266 default:
1267
1268 if (pixtypes_len) pfree(pixtypes);
1269
1271 PG_FREE_IF_COPY(gser, 0);
1272
1273 elog(ERROR, "RASTER_asRaster: Invalid data type for value");
1274 PG_RETURN_NULL();
1275 break;
1276 }
1277
1278 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1279 &nulls, &n);
1280
1281 if (n) {
1282 values = (double *) palloc(sizeof(double) * n);
1283 for (i = 0, j = 0; i < n; i++) {
1284 if (nulls[i]) {
1285 values[j++] = 1;
1286 continue;
1287 }
1288
1289 switch (etype) {
1290 case FLOAT4OID:
1291 values[j] = (double) DatumGetFloat4(e[i]);
1292 break;
1293 case FLOAT8OID:
1294 values[j] = (double) DatumGetFloat8(e[i]);
1295 break;
1296 }
1298
1299 j++;
1300 }
1301
1302 if (j > 0) {
1303
1304 values = repalloc(values, j * sizeof(double));
1305 values_len = j;
1306 }
1307 else {
1308 pfree(values);
1309 values = NULL;
1310 values_len = 0;
1311 }
1312 }
1313 }
1314#if POSTGIS_DEBUG_LEVEL > 0
1315 for (uint32_t u = 0; u < values_len; u++)
1317#endif
1318
1319
1320 if (!PG_ARGISNULL(7)) {
1321 array = PG_GETARG_ARRAYTYPE_P(7);
1322 etype = ARR_ELEMTYPE(array);
1323 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1324
1325 switch (etype) {
1326 case FLOAT4OID:
1327 case FLOAT8OID:
1328 break;
1329 default:
1330
1331 if (pixtypes_len) pfree(pixtypes);
1332 if (values_len) pfree(values);
1333
1335 PG_FREE_IF_COPY(gser, 0);
1336
1337 elog(ERROR, "RASTER_asRaster: Invalid data type for nodataval");
1338 PG_RETURN_NULL();
1339 break;
1340 }
1341
1342 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1343 &nulls, &n);
1344
1345 if (n) {
1346 nodatavals = (double *) palloc(sizeof(double) * n);
1347 hasnodatas = (uint8_t *) palloc(sizeof(uint8_t) * n);
1348 for (i = 0, j = 0; i < n; i++) {
1349 if (nulls[i]) {
1350 hasnodatas[j] = 0;
1351 nodatavals[j] = 0;
1352 j++;
1353 continue;
1354 }
1355
1356 hasnodatas[j] = 1;
1357 switch (etype) {
1358 case FLOAT4OID:
1359 nodatavals[j] = (double) DatumGetFloat4(e[i]);
1360 break;
1361 case FLOAT8OID:
1362 nodatavals[j] = (double) DatumGetFloat8(e[i]);
1363 break;
1364 }
1367
1368 j++;
1369 }
1370
1371 if (j > 0) {
1372
1373 nodatavals = repalloc(nodatavals, j * sizeof(double));
1374 hasnodatas = repalloc(hasnodatas, j * sizeof(uint8_t));
1375 nodatavals_len = j;
1376 }
1377 else {
1378 pfree(nodatavals);
1379 pfree(hasnodatas);
1380 nodatavals = NULL;
1381 hasnodatas = NULL;
1382 nodatavals_len = 0;
1383 }
1384 }
1385 }
1386#if POSTGIS_DEBUG_LEVEL > 0
1387 for (uint32_t u = 0; u < nodatavals_len; u++)
1388 {
1391 }
1392#endif
1393
1394
1395 if (!PG_ARGISNULL(8)) {
1396 ulw[0] = PG_GETARG_FLOAT8(8);
1397 ul_xw = &ulw[0];
1398 }
1399
1400
1401 if (!PG_ARGISNULL(9)) {
1402 ulw[1] = PG_GETARG_FLOAT8(9);
1403 ul_yw = &ulw[1];
1404 }
1405 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: upperleft (x, y) = %f, %f", ulw[0], ulw[1]);
1406
1407
1408 if (!PG_ARGISNULL(10)) {
1409 gridw[0] = PG_GETARG_FLOAT8(10);
1410 grid_xw = &gridw[0];
1411 }
1412
1413
1414 if (!PG_ARGISNULL(11)) {
1415 gridw[1] = PG_GETARG_FLOAT8(11);
1416 grid_yw = &gridw[1];
1417 }
1418 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: grid (x, y) = %f, %f", gridw[0], gridw[1]);
1419
1420
1421 haserr = 0;
1422 do {
1423
1424 if (
1425 (scale_x == NULL && scale_y != NULL) ||
1426 (scale_x != NULL && scale_y == NULL)
1427 ) {
1428 elog(NOTICE, "Values must be provided for both X and Y of scale if one is specified");
1429 haserr = 1;
1430 break;
1431 }
1432
1433
1434 if (
1435 (dim_x == NULL && dim_y != NULL) ||
1436 (dim_x != NULL && dim_y == NULL)
1437 ) {
1438 elog(NOTICE, "Values must be provided for both width and height if one is specified");
1439 haserr = 1;
1440 break;
1441 }
1442
1443
1444 if (
1445 (scale_x != NULL && scale_y != NULL) &&
1446 (dim_x != NULL && dim_y != NULL)
1447 ) {
1448 elog(NOTICE, "Values provided for X and Y of scale and width and height. Using the width and height");
1449 scale_x = NULL;
1450 scale_y = NULL;
1451 break;
1452 }
1453
1454
1455 if (
1456 (scale_x == NULL && scale_y == NULL) &&
1457 (dim_x == NULL && dim_y == NULL)
1458 ) {
1459 elog(NOTICE, "Values must be provided for X and Y of scale or width and height");
1460 haserr = 1;
1461 break;
1462 }
1463
1464
1465 if (
1466 (ul_xw == NULL && ul_yw != NULL) ||
1467 (ul_xw != NULL && ul_yw == NULL)
1468 ) {
1469 elog(NOTICE, "Values must be provided for both X and Y when specifying the upper-left corner");
1470 haserr = 1;
1471 break;
1472 }
1473
1474
1475 if (
1476 (grid_xw == NULL && grid_yw != NULL) ||
1477 (grid_xw != NULL && grid_yw == NULL)
1478 ) {
1479 elog(NOTICE, "Values must be provided for both X and Y when specifying the alignment");
1480 haserr = 1;
1481 break;
1482 }
1483
1484
1485 if (
1486 (ul_xw != NULL && ul_yw != NULL) &&
1487 (grid_xw != NULL && grid_yw != NULL)
1488 ) {
1489 elog(NOTICE, "Values provided for both X and Y of upper-left corner and alignment. Using the values of upper-left corner");
1490 grid_xw = NULL;
1491 grid_yw = NULL;
1492 break;
1493 }
1494 }
1495 while (0);
1496
1497 if (haserr) {
1498 if (pixtypes_len) pfree(pixtypes);
1499 if (values_len) pfree(values);
1500 if (nodatavals_len) {
1501 pfree(nodatavals);
1502 pfree(hasnodatas);
1503 }
1504
1506 PG_FREE_IF_COPY(gser, 0);
1507
1508 PG_RETURN_NULL();
1509 }
1510
1511
1512 if (!PG_ARGISNULL(12)) {
1513 skew[0] = PG_GETARG_FLOAT8(12);
1515 skew_x = &skew[0];
1516 }
1517
1518
1519 if (!PG_ARGISNULL(13)) {
1520 skew[1] = PG_GETARG_FLOAT8(13);
1522 skew_y = &skew[1];
1523 }
1524 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: skew (x, y) = %f, %f", skew[0], skew[1]);
1525
1526
1527 if (!PG_ARGISNULL(14) && PG_GETARG_BOOL(14) ==
TRUE) {
1528 if (options_len == 0) {
1529 options_len = 1;
1530 options = (char **) palloc(sizeof(char *) * options_len);
1531 }
1532 else {
1533 options_len++;
1534 options = (char **) repalloc(options, sizeof(char *) * options_len);
1535 }
1536
1537 options[options_len - 1] = palloc(sizeof(char*) * (strlen("ALL_TOUCHED=TRUE") + 1));
1538 strcpy(options[options_len - 1], "ALL_TOUCHED=TRUE");
1539 }
1540
1541 if (options_len) {
1542 options_len++;
1543 options = (char **) repalloc(options, sizeof(char *) * options_len);
1544 options[options_len - 1] = NULL;
1545 }
1546
1547
1549
1553 if (NULL == srs) {
1554
1555 if (pixtypes_len) pfree(pixtypes);
1556 if (values_len) pfree(values);
1557 if (nodatavals_len) {
1558 pfree(hasnodatas);
1559 pfree(nodatavals);
1560 }
1561 if (options_len) pfree(options);
1562
1564 PG_FREE_IF_COPY(gser, 0);
1565
1566 elog(ERROR, "RASTER_asRaster: Could not find srtext for SRID (%d)", srid);
1567 PG_RETURN_NULL();
1568 }
1570 }
1571 else
1572 srs = NULL;
1573
1574
1575
1576 num_bands =
MIN(pixtypes_len, values_len);
1577 num_bands =
MIN(num_bands, nodatavals_len);
1582
1583
1584 if (!(
1585 (pixtypes_len == values_len) &&
1586 (values_len == nodatavals_len)
1587 )) {
1588 elog(
1589 NOTICE,
1590 "Imbalanced number of values provided for pixeltype (%d), value (%d) and nodataval (%d). Using the first %d values of each parameter",
1591 pixtypes_len,
1592 values_len,
1593 nodatavals_len,
1594 num_bands
1595 );
1596 }
1597
1598
1602 PG_FREE_IF_COPY(gser, 0);
1603
1604
1606
1609 srs,
1610 num_bands,
1611 pixtypes,
1612 nodatavals,
1613 values,
1614 nodatavals,
1615 hasnodatas,
1616 dim_x,
1617 dim_y,
1618 scale_x,
1619 scale_y,
1620 ul_xw,
1621 ul_yw,
1622 grid_xw,
1623 grid_yw,
1624 skew_x,
1625 skew_y,
1626 options);
1627
1628 if (pixtypes_len) pfree(pixtypes);
1629 if (values_len) pfree(values);
1630 if (nodatavals_len) {
1631 pfree(hasnodatas);
1632 pfree(nodatavals);
1633 }
1634 if (options_len) pfree(options);
1635
1636 if (!rast) {
1637 elog(ERROR, "RASTER_asRaster: Could not rasterize geometry");
1638 PG_RETURN_NULL();
1639 }
1640
1641
1643
1646
1647 if (NULL == pgrast) PG_RETURN_NULL();
1648
1650
1651 SET_VARSIZE(pgrast, pgrast->
size);
1652 PG_RETURN_POINTER(pgrast);
1653}
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
void lwgeom_free(LWGEOM *geom)
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
lwvarlena_t * lwgeom_to_wkb_varlena(const LWGEOM *geom, uint8_t variant)
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
#define SRID_UNKNOWN
Unknown SRID value.
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
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_gdal_rasterize(const unsigned char *wkb, uint32_t wkb_len, const char *srs, uint32_t num_bands, rt_pixtype *pixtype, double *init, double *value, double *nodata, uint8_t *hasnodata, int *width, int *height, double *scale_x, double *scale_y, double *ul_xw, double *ul_yw, double *grid_xw, double *grid_yw, double *skew_x, double *skew_y, char **options)
Return a raster of the provided geometry.
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
char * rtpg_getSR(int32_t srid)
char * rtpg_trim(const char *input)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)