724{
726
730
731 unsigned char *wkb;
732 size_t wkb_len = 0;
734
735 double scale[2] = {0};
736 double *scale_x = NULL;
737 double *scale_y = NULL;
738
739 int dim[2] = {0};
740 int *dim_x = NULL;
741 int *dim_y = NULL;
742
743 ArrayType *array;
744 Oid etype;
745 Datum *e;
746 bool *nulls;
747 int16 typlen;
748 bool typbyval;
749 char typalign;
750 int n = 0;
751 int i = 0;
752 int j = 0;
753 int haserr = 0;
754
755 text *pixeltypetext = NULL;
756 char *pixeltype = NULL;
759 uint32_t pixtypes_len = 0;
760
761 double *values = NULL;
762 uint32_t values_len = 0;
763
764 uint8_t *hasnodatas = NULL;
765 double *nodatavals = NULL;
766 uint32_t nodatavals_len = 0;
767
768 double ulw[2] = {0};
769 double *ul_xw = NULL;
770 double *ul_yw = NULL;
771
772 double gridw[2] = {0};
773 double *grid_xw = NULL;
774 double *grid_yw = NULL;
775
776 double skew[2] = {0};
777 double *skew_x = NULL;
778 double *skew_y = NULL;
779
780 char **options = NULL;
781 int options_len = 0;
782
783 uint32_t num_bands = 0;
784
786 char *srs = NULL;
787
789
790
791
792
793 if (PG_ARGISNULL(0))
794 PG_RETURN_NULL();
795
796 gser = PG_GETARG_GSERIALIZED_P(0);
798
799
803 geom = geom2d;
804 }
805
806
810 PG_FREE_IF_COPY(gser, 0);
811
813 if (rast == NULL)
814 PG_RETURN_NULL();
815
818
819 if (NULL == pgrast)
820 PG_RETURN_NULL();
821
822 SET_VARSIZE(pgrast, pgrast->
size);
823 PG_RETURN_POINTER(pgrast);
824 }
825
826
827 if (!PG_ARGISNULL(1)) {
828 scale[0] = PG_GETARG_FLOAT8(1);
830 scale_x = &scale[0];
831 }
832
833
834 if (!PG_ARGISNULL(2)) {
835 scale[1] = PG_GETARG_FLOAT8(2);
837 scale_y = &scale[1];
838 }
839 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: scale (x, y) = %f, %f", scale[0], scale[1]);
840
841
842 if (!PG_ARGISNULL(3)) {
843 dim[0] = PG_GETARG_INT32(3);
844 if (dim[0] < 0) dim[0] = 0;
845 if (dim[0] != 0) dim_x = &dim[0];
846 }
847
848
849 if (!PG_ARGISNULL(4)) {
850 dim[1] = PG_GETARG_INT32(4);
851 if (dim[1] < 0) dim[1] = 0;
852 if (dim[1] != 0) dim_y = &dim[1];
853 }
855
856
857 if (!PG_ARGISNULL(5)) {
858 array = PG_GETARG_ARRAYTYPE_P(5);
859 etype = ARR_ELEMTYPE(array);
860 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
861
862 switch (etype) {
863 case TEXTOID:
864 break;
865 default:
866
868 PG_FREE_IF_COPY(gser, 0);
869
870 elog(ERROR, "RASTER_asRaster: Invalid data type for pixeltype");
871 PG_RETURN_NULL();
872 break;
873 }
874
875 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
876 &nulls, &n);
877
878 if (n) {
880
881 for (i = 0, j = 0; i < n; i++) {
882 if (nulls[i]) {
884 continue;
885 }
886
887 pixeltype = NULL;
888 switch (etype) {
889 case TEXTOID:
890 pixeltypetext = (text *) DatumGetPointer(e[i]);
891 if (NULL == pixeltypetext) break;
893
894
897 break;
898 }
899
900 if (strlen(pixeltype)) {
903
904 pfree(pixtypes);
905
907 PG_FREE_IF_COPY(gser, 0);
908
909 elog(ERROR, "RASTER_asRaster: Invalid pixel type provided: %s", pixeltype);
910 PG_RETURN_NULL();
911 }
912
913 pixtypes[j] = pixtype;
914 j++;
915 }
916 }
917
918 if (j > 0) {
919
920 pixtypes = repalloc(pixtypes, j *
sizeof(
rt_pixtype));
921 pixtypes_len = j;
922 }
923 else {
924 pfree(pixtypes);
925 pixtypes = NULL;
926 pixtypes_len = 0;
927 }
928 }
929 }
930#if POSTGIS_DEBUG_LEVEL > 0
931 for (uint32_t u = 0; u < pixtypes_len; u++)
933#endif
934
935
936 if (!PG_ARGISNULL(6)) {
937 array = PG_GETARG_ARRAYTYPE_P(6);
938 etype = ARR_ELEMTYPE(array);
939 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
940
941 switch (etype) {
942 case FLOAT4OID:
943 case FLOAT8OID:
944 break;
945 default:
946
947 if (pixtypes_len) pfree(pixtypes);
948
950 PG_FREE_IF_COPY(gser, 0);
951
952 elog(ERROR, "RASTER_asRaster: Invalid data type for value");
953 PG_RETURN_NULL();
954 break;
955 }
956
957 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
958 &nulls, &n);
959
960 if (n) {
961 values = (double *) palloc(sizeof(double) * n);
962 for (i = 0, j = 0; i < n; i++) {
963 if (nulls[i]) {
964 values[j++] = 1;
965 continue;
966 }
967
968 switch (etype) {
969 case FLOAT4OID:
970 values[j] = (double) DatumGetFloat4(e[i]);
971 break;
972 case FLOAT8OID:
973 values[j] = (double) DatumGetFloat8(e[i]);
974 break;
975 }
977
978 j++;
979 }
980
981 if (j > 0) {
982
983 values = repalloc(values, j * sizeof(double));
984 values_len = j;
985 }
986 else {
987 pfree(values);
988 values = NULL;
989 values_len = 0;
990 }
991 }
992 }
993#if POSTGIS_DEBUG_LEVEL > 0
994 for (uint32_t u = 0; u < values_len; u++)
996#endif
997
998
999 if (!PG_ARGISNULL(7)) {
1000 array = PG_GETARG_ARRAYTYPE_P(7);
1001 etype = ARR_ELEMTYPE(array);
1002 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1003
1004 switch (etype) {
1005 case FLOAT4OID:
1006 case FLOAT8OID:
1007 break;
1008 default:
1009
1010 if (pixtypes_len) pfree(pixtypes);
1011 if (values_len) pfree(values);
1012
1014 PG_FREE_IF_COPY(gser, 0);
1015
1016 elog(ERROR, "RASTER_asRaster: Invalid data type for nodataval");
1017 PG_RETURN_NULL();
1018 break;
1019 }
1020
1021 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1022 &nulls, &n);
1023
1024 if (n) {
1025 nodatavals = (double *) palloc(sizeof(double) * n);
1026 hasnodatas = (uint8_t *) palloc(sizeof(uint8_t) * n);
1027 for (i = 0, j = 0; i < n; i++) {
1028 if (nulls[i]) {
1029 hasnodatas[j] = 0;
1030 nodatavals[j] = 0;
1031 j++;
1032 continue;
1033 }
1034
1035 hasnodatas[j] = 1;
1036 switch (etype) {
1037 case FLOAT4OID:
1038 nodatavals[j] = (double) DatumGetFloat4(e[i]);
1039 break;
1040 case FLOAT8OID:
1041 nodatavals[j] = (double) DatumGetFloat8(e[i]);
1042 break;
1043 }
1046
1047 j++;
1048 }
1049
1050 if (j > 0) {
1051
1052 nodatavals = repalloc(nodatavals, j * sizeof(double));
1053 hasnodatas = repalloc(hasnodatas, j * sizeof(uint8_t));
1054 nodatavals_len = j;
1055 }
1056 else {
1057 pfree(nodatavals);
1058 pfree(hasnodatas);
1059 nodatavals = NULL;
1060 hasnodatas = NULL;
1061 nodatavals_len = 0;
1062 }
1063 }
1064 }
1065#if POSTGIS_DEBUG_LEVEL > 0
1066 for (uint32_t u = 0; u < nodatavals_len; u++)
1067 {
1070 }
1071#endif
1072
1073
1074 if (!PG_ARGISNULL(8)) {
1075 ulw[0] = PG_GETARG_FLOAT8(8);
1076 ul_xw = &ulw[0];
1077 }
1078
1079
1080 if (!PG_ARGISNULL(9)) {
1081 ulw[1] = PG_GETARG_FLOAT8(9);
1082 ul_yw = &ulw[1];
1083 }
1084 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: upperleft (x, y) = %f, %f", ulw[0], ulw[1]);
1085
1086
1087 if (!PG_ARGISNULL(10)) {
1088 gridw[0] = PG_GETARG_FLOAT8(10);
1089 grid_xw = &gridw[0];
1090 }
1091
1092
1093 if (!PG_ARGISNULL(11)) {
1094 gridw[1] = PG_GETARG_FLOAT8(11);
1095 grid_yw = &gridw[1];
1096 }
1097 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: grid (x, y) = %f, %f", gridw[0], gridw[1]);
1098
1099
1100 haserr = 0;
1101 do {
1102
1103 if (
1104 (scale_x == NULL && scale_y != NULL) ||
1105 (scale_x != NULL && scale_y == NULL)
1106 ) {
1107 elog(NOTICE, "Values must be provided for both X and Y of scale if one is specified");
1108 haserr = 1;
1109 break;
1110 }
1111
1112
1113 if (
1114 (dim_x == NULL && dim_y != NULL) ||
1115 (dim_x != NULL && dim_y == NULL)
1116 ) {
1117 elog(NOTICE, "Values must be provided for both width and height if one is specified");
1118 haserr = 1;
1119 break;
1120 }
1121
1122
1123 if (
1124 (scale_x != NULL && scale_y != NULL) &&
1125 (dim_x != NULL && dim_y != NULL)
1126 ) {
1127 elog(NOTICE, "Values provided for X and Y of scale and width and height. Using the width and height");
1128 scale_x = NULL;
1129 scale_y = NULL;
1130 break;
1131 }
1132
1133
1134 if (
1135 (scale_x == NULL && scale_y == NULL) &&
1136 (dim_x == NULL && dim_y == NULL)
1137 ) {
1138 elog(NOTICE, "Values must be provided for X and Y of scale or width and height");
1139 haserr = 1;
1140 break;
1141 }
1142
1143
1144 if (
1145 (ul_xw == NULL && ul_yw != NULL) ||
1146 (ul_xw != NULL && ul_yw == NULL)
1147 ) {
1148 elog(NOTICE, "Values must be provided for both X and Y when specifying the upper-left corner");
1149 haserr = 1;
1150 break;
1151 }
1152
1153
1154 if (
1155 (grid_xw == NULL && grid_yw != NULL) ||
1156 (grid_xw != NULL && grid_yw == NULL)
1157 ) {
1158 elog(NOTICE, "Values must be provided for both X and Y when specifying the alignment");
1159 haserr = 1;
1160 break;
1161 }
1162
1163
1164 if (
1165 (ul_xw != NULL && ul_yw != NULL) &&
1166 (grid_xw != NULL && grid_yw != NULL)
1167 ) {
1168 elog(NOTICE, "Values provided for both X and Y of upper-left corner and alignment. Using the values of upper-left corner");
1169 grid_xw = NULL;
1170 grid_yw = NULL;
1171 break;
1172 }
1173 }
1174 while (0);
1175
1176 if (haserr) {
1177 if (pixtypes_len) pfree(pixtypes);
1178 if (values_len) pfree(values);
1179 if (nodatavals_len) {
1180 pfree(nodatavals);
1181 pfree(hasnodatas);
1182 }
1183
1185 PG_FREE_IF_COPY(gser, 0);
1186
1187 PG_RETURN_NULL();
1188 }
1189
1190
1191 if (!PG_ARGISNULL(12)) {
1192 skew[0] = PG_GETARG_FLOAT8(12);
1194 skew_x = &skew[0];
1195 }
1196
1197
1198 if (!PG_ARGISNULL(13)) {
1199 skew[1] = PG_GETARG_FLOAT8(13);
1201 skew_y = &skew[1];
1202 }
1203 POSTGIS_RT_DEBUGF(3,
"RASTER_asRaster: skew (x, y) = %f, %f", skew[0], skew[1]);
1204
1205
1206 if (!PG_ARGISNULL(14) && PG_GETARG_BOOL(14) ==
TRUE) {
1207 if (options_len == 0) {
1208 options_len = 1;
1209 options = (char **) palloc(sizeof(char *) * options_len);
1210 }
1211 else {
1212 options_len++;
1213 options = (char **) repalloc(options, sizeof(char *) * options_len);
1214 }
1215
1216 options[options_len - 1] = palloc(sizeof(char*) * (strlen("ALL_TOUCHED=TRUE") + 1));
1217 strcpy(options[options_len - 1], "ALL_TOUCHED=TRUE");
1218 }
1219
1220 if (options_len) {
1221 options_len++;
1222 options = (char **) repalloc(options, sizeof(char *) * options_len);
1223 options[options_len - 1] = NULL;
1224 }
1225
1226
1228
1232 if (NULL == srs) {
1233
1234 if (pixtypes_len) pfree(pixtypes);
1235 if (values_len) pfree(values);
1236 if (nodatavals_len) {
1237 pfree(hasnodatas);
1238 pfree(nodatavals);
1239 }
1240 if (options_len) pfree(options);
1241
1243 PG_FREE_IF_COPY(gser, 0);
1244
1245 elog(ERROR, "RASTER_asRaster: Could not find srtext for SRID (%d)", srid);
1246 PG_RETURN_NULL();
1247 }
1249 }
1250 else
1251 srs = NULL;
1252
1253
1254
1255 num_bands =
MIN(pixtypes_len, values_len);
1256 num_bands =
MIN(num_bands, nodatavals_len);
1261
1262
1263 if (!(
1264 (pixtypes_len == values_len) &&
1265 (values_len == nodatavals_len)
1266 )) {
1267 elog(
1268 NOTICE,
1269 "Imbalanced number of values provided for pixeltype (%d), value (%d) and nodataval (%d). Using the first %d values of each parameter",
1270 pixtypes_len,
1271 values_len,
1272 nodatavals_len,
1273 num_bands
1274 );
1275 }
1276
1277
1281 PG_FREE_IF_COPY(gser, 0);
1282
1283
1285
1287 (uint32_t) wkb_len, srs,
1288 num_bands, pixtypes,
1289 nodatavals, values,
1290 nodatavals, hasnodatas,
1291 dim_x, dim_y,
1292 scale_x, scale_y,
1293 ul_xw, ul_yw,
1294 grid_xw, grid_yw,
1295 skew_x, skew_y,
1296 options
1297 );
1298
1299 if (pixtypes_len) pfree(pixtypes);
1300 if (values_len) pfree(values);
1301 if (nodatavals_len) {
1302 pfree(hasnodatas);
1303 pfree(nodatavals);
1304 }
1305 if (options_len) pfree(options);
1306
1307 if (!rast) {
1308 elog(ERROR, "RASTER_asRaster: Could not rasterize geometry");
1309 PG_RETURN_NULL();
1310 }
1311
1312
1314
1317
1318 if (NULL == pgrast) PG_RETURN_NULL();
1319
1321
1322 SET_VARSIZE(pgrast, pgrast->
size);
1323 PG_RETURN_POINTER(pgrast);
1324}
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)
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
uint8_t * lwgeom_to_wkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Convert LWGEOM to a char* in WKB format.
#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 * text_to_cstring(const text *textptr)
char * rtpg_getSR(int32_t srid)
char * rtpg_trim(const char *input)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)