PostGIS  2.5.1dev-r@@SVN_REVISION@@

◆ RASTER_mapAlgebra2()

Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6079 of file rtpg_mapalgebra.c.

References ARGKWCOUNT, ovdump::band, ES_NONE, ET_CUSTOM, ET_FIRST, ET_INTERSECTION, ET_LAST, ET_SECOND, ET_UNION, FALSE, window::gt, pixval::pixel, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, PT_END, rtpixdump::rast, rtrowdump::raster, rt_band_get_hasnodata_flag(), rt_band_get_nodata(), rt_band_get_pixel(), rt_band_get_pixtype(), rt_band_set_pixel(), rt_pixtype_get_min_value(), rt_pixtype_index_from_name(), rt_pixtype_name(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_from_two_rasters(), rt_raster_generate_new_band(), rt_raster_get_band(), rt_raster_get_geotransform_matrix(), rt_raster_get_height(), rt_raster_get_srid(), rt_raster_get_width(), rt_raster_get_x_offset(), rt_raster_get_x_scale(), rt_raster_get_x_skew(), rt_raster_get_y_offset(), rt_raster_get_y_scale(), rt_raster_get_y_skew(), rt_raster_has_band(), rt_raster_is_empty(), rt_raster_new(), rt_raster_same_alignment(), rt_raster_serialize(), rt_raster_set_geotransform_matrix(), rt_raster_set_scale(), rt_raster_set_srid(), rt_util_extent_type(), rtpg_strreplace(), rtpg_strtoupper(), rtpg_trim(), rt_raster_serialized_t::size, rtgdalraster::sql, text_to_cstring(), TRUE, pixval::x, and pixval::y.

6080 {
6081  const uint32_t set_count = 2;
6082  rt_pgraster *pgrast[2] = { NULL, NULL };
6083  int pgrastpos[2] = {-1, -1};
6084  rt_pgraster *pgrtn;
6085  rt_raster rast[2] = {NULL};
6086  int _isempty[2] = {0};
6087  uint32_t bandindex[2] = {0};
6088  rt_raster _rast[2] = {NULL};
6089  rt_band _band[2] = {NULL};
6090  int _hasnodata[2] = {0};
6091  double _nodataval[2] = {0};
6092  double _offset[4] = {0.};
6093  double _rastoffset[2][4] = {{0.}};
6094  int _haspixel[2] = {0};
6095  double _pixel[2] = {0};
6096  int _pos[2][2] = {{0}};
6097  uint16_t _dim[2][2] = {{0}};
6098 
6099  char *pixtypename = NULL;
6100  rt_pixtype pixtype = PT_END;
6101  char *extenttypename = NULL;
6102  rt_extenttype extenttype = ET_INTERSECTION;
6103 
6104  rt_raster raster = NULL;
6105  rt_band band = NULL;
6106  uint16_t dim[2] = {0};
6107  int haspixel = 0;
6108  double pixel = 0.;
6109  double nodataval = 0;
6110  double gt[6] = {0.};
6111 
6112  Oid calltype = InvalidOid;
6113 
6114  const uint32_t spi_count = 3;
6115  uint16_t spi_exprpos[3] = {4, 7, 8};
6116  uint32_t spi_argcount[3] = {0};
6117  char *expr = NULL;
6118  char *sql = NULL;
6119  SPIPlanPtr spi_plan[3] = {NULL};
6120  uint16_t spi_empty = 0;
6121  Oid *argtype = NULL;
6122  uint8_t argpos[3][8] = {{0}};
6123  char *argkw[] = {"[rast1.x]", "[rast1.y]", "[rast1.val]", "[rast1]", "[rast2.x]", "[rast2.y]", "[rast2.val]", "[rast2]"};
6124  Datum values[ARGKWCOUNT];
6125  char nulls[ARGKWCOUNT];
6126  TupleDesc tupdesc;
6127  SPITupleTable *tuptable = NULL;
6128  HeapTuple tuple;
6129  Datum datum;
6130  bool isnull = FALSE;
6131  int hasargval[3] = {0};
6132  double argval[3] = {0.};
6133  int hasnodatanodataval = 0;
6134  double nodatanodataval = 0;
6135  int isnodata = 0;
6136 
6137  Oid ufc_noid = InvalidOid;
6138  FmgrInfo ufl_info;
6139  FunctionCallInfoData ufc_info;
6140  int ufc_nullcount = 0;
6141 
6142  int idx = 0;
6143  uint32_t i = 0;
6144  uint32_t j = 0;
6145  uint32_t k = 0;
6146  uint32_t x = 0;
6147  uint32_t y = 0;
6148  int _x = 0;
6149  int _y = 0;
6150  int err;
6151  int aligned = 0;
6152  int len = 0;
6153 
6154  POSTGIS_RT_DEBUG(3, "Starting RASTER_mapAlgebra2");
6155 
6156  for (i = 0, j = 0; i < set_count; i++) {
6157  if (!PG_ARGISNULL(j)) {
6158  pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
6159  pgrastpos[i] = j;
6160  j++;
6161 
6162  /* raster */
6163  rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
6164  if (!rast[i]) {
6165  for (k = 0; k <= i; k++) {
6166  if (k < i && rast[k] != NULL)
6167  rt_raster_destroy(rast[k]);
6168  if (pgrastpos[k] != -1)
6169  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6170  }
6171  elog(ERROR, "RASTER_mapAlgebra2: Could not deserialize the %s raster", i < 1 ? "first" : "second");
6172  PG_RETURN_NULL();
6173  }
6174 
6175  /* empty */
6176  _isempty[i] = rt_raster_is_empty(rast[i]);
6177 
6178  /* band index */
6179  if (!PG_ARGISNULL(j)) {
6180  bandindex[i] = PG_GETARG_INT32(j);
6181  }
6182  j++;
6183  }
6184  else {
6185  _isempty[i] = 1;
6186  j += 2;
6187  }
6188 
6189  POSTGIS_RT_DEBUGF(3, "_isempty[%d] = %d", i, _isempty[i]);
6190  }
6191 
6192  /* both rasters are NULL */
6193  if (rast[0] == NULL && rast[1] == NULL) {
6194  elog(NOTICE, "The two rasters provided are NULL. Returning NULL");
6195  for (k = 0; k < set_count; k++) {
6196  if (pgrastpos[k] != -1)
6197  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6198  }
6199  PG_RETURN_NULL();
6200  }
6201 
6202  /* both rasters are empty */
6203  if (_isempty[0] && _isempty[1]) {
6204  elog(NOTICE, "The two rasters provided are empty. Returning empty raster");
6205 
6206  raster = rt_raster_new(0, 0);
6207  if (raster == NULL) {
6208  for (k = 0; k < set_count; k++) {
6209  if (rast[k] != NULL)
6210  rt_raster_destroy(rast[k]);
6211  if (pgrastpos[k] != -1)
6212  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6213  }
6214  elog(ERROR, "RASTER_mapAlgebra2: Could not create empty raster");
6215  PG_RETURN_NULL();
6216  }
6217  rt_raster_set_scale(raster, 0, 0);
6218 
6219  pgrtn = rt_raster_serialize(raster);
6220  rt_raster_destroy(raster);
6221  if (!pgrtn)
6222  PG_RETURN_NULL();
6223 
6224  SET_VARSIZE(pgrtn, pgrtn->size);
6225  PG_RETURN_POINTER(pgrtn);
6226  }
6227 
6228  /* replace the empty or NULL raster with one matching the other */
6229  if (
6230  (rast[0] == NULL || _isempty[0]) ||
6231  (rast[1] == NULL || _isempty[1])
6232  ) {
6233  /* first raster is empty */
6234  if (rast[0] == NULL || _isempty[0]) {
6235  i = 0;
6236  j = 1;
6237  }
6238  /* second raster is empty */
6239  else {
6240  i = 1;
6241  j = 0;
6242  }
6243 
6244  _rast[j] = rast[j];
6245 
6246  /* raster is empty, destroy it */
6247  if (_rast[i] != NULL)
6248  rt_raster_destroy(_rast[i]);
6249 
6250  _dim[i][0] = rt_raster_get_width(_rast[j]);
6251  _dim[i][1] = rt_raster_get_height(_rast[j]);
6252  _dim[j][0] = rt_raster_get_width(_rast[j]);
6253  _dim[j][1] = rt_raster_get_height(_rast[j]);
6254 
6255  _rast[i] = rt_raster_new(
6256  _dim[j][0],
6257  _dim[j][1]
6258  );
6259  if (_rast[i] == NULL) {
6260  rt_raster_destroy(_rast[j]);
6261  for (k = 0; k < set_count; k++) {
6262  if (pgrastpos[k] != -1)
6263  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6264  }
6265  elog(ERROR, "RASTER_mapAlgebra2: Could not create NODATA raster");
6266  PG_RETURN_NULL();
6267  }
6268  rt_raster_set_srid(_rast[i], rt_raster_get_srid(_rast[j]));
6269 
6270  rt_raster_get_geotransform_matrix(_rast[j], gt);
6271  rt_raster_set_geotransform_matrix(_rast[i], gt);
6272  }
6273  else {
6274  _rast[0] = rast[0];
6275  _dim[0][0] = rt_raster_get_width(_rast[0]);
6276  _dim[0][1] = rt_raster_get_height(_rast[0]);
6277 
6278  _rast[1] = rast[1];
6279  _dim[1][0] = rt_raster_get_width(_rast[1]);
6280  _dim[1][1] = rt_raster_get_height(_rast[1]);
6281  }
6282 
6283  /* SRID must match */
6284  /*
6285  if (rt_raster_get_srid(_rast[0]) != rt_raster_get_srid(_rast[1])) {
6286  elog(NOTICE, "The two rasters provided have different SRIDs. Returning NULL");
6287  for (k = 0; k < set_count; k++) {
6288  if (_rast[k] != NULL)
6289  rt_raster_destroy(_rast[k]);
6290  if (pgrastpos[k] != -1)
6291  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6292  }
6293  PG_RETURN_NULL();
6294  }
6295  */
6296 
6297  /* same alignment */
6298  if (rt_raster_same_alignment(_rast[0], _rast[1], &aligned, NULL) != ES_NONE) {
6299  for (k = 0; k < set_count; k++) {
6300  if (_rast[k] != NULL)
6301  rt_raster_destroy(_rast[k]);
6302  if (pgrastpos[k] != -1)
6303  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6304  }
6305  elog(ERROR, "RASTER_mapAlgebra2: Could not test for alignment on the two rasters");
6306  PG_RETURN_NULL();
6307  }
6308  if (!aligned) {
6309  elog(NOTICE, "The two rasters provided do not have the same alignment. Returning NULL");
6310  for (k = 0; k < set_count; k++) {
6311  if (_rast[k] != NULL)
6312  rt_raster_destroy(_rast[k]);
6313  if (pgrastpos[k] != -1)
6314  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6315  }
6316  PG_RETURN_NULL();
6317  }
6318 
6319  /* pixel type */
6320  if (!PG_ARGISNULL(5)) {
6321  pixtypename = text_to_cstring(PG_GETARG_TEXT_P(5));
6322  /* Get the pixel type index */
6323  pixtype = rt_pixtype_index_from_name(pixtypename);
6324  if (pixtype == PT_END ) {
6325  for (k = 0; k < set_count; k++) {
6326  if (_rast[k] != NULL)
6327  rt_raster_destroy(_rast[k]);
6328  if (pgrastpos[k] != -1)
6329  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6330  }
6331  elog(ERROR, "RASTER_mapAlgebra2: Invalid pixel type: %s", pixtypename);
6332  PG_RETURN_NULL();
6333  }
6334  }
6335 
6336  /* extent type */
6337  if (!PG_ARGISNULL(6)) {
6338  extenttypename = rtpg_strtoupper(rtpg_trim(text_to_cstring(PG_GETARG_TEXT_P(6))));
6339  extenttype = rt_util_extent_type(extenttypename);
6340  }
6341  POSTGIS_RT_DEBUGF(3, "extenttype: %d %s", extenttype, extenttypename);
6342 
6343  /* computed raster from extent type */
6345  _rast[0], _rast[1],
6346  extenttype,
6347  &raster, _offset
6348  );
6349  if (err != ES_NONE) {
6350  for (k = 0; k < set_count; k++) {
6351  if (_rast[k] != NULL)
6352  rt_raster_destroy(_rast[k]);
6353  if (pgrastpos[k] != -1)
6354  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6355  }
6356  elog(ERROR, "RASTER_mapAlgebra2: Could not get output raster of correct extent");
6357  PG_RETURN_NULL();
6358  }
6359 
6360  /* copy offsets */
6361  _rastoffset[0][0] = _offset[0];
6362  _rastoffset[0][1] = _offset[1];
6363  _rastoffset[1][0] = _offset[2];
6364  _rastoffset[1][1] = _offset[3];
6365 
6366  /* get output raster dimensions */
6367  dim[0] = rt_raster_get_width(raster);
6368  dim[1] = rt_raster_get_height(raster);
6369 
6370  i = 2;
6371  /* handle special cases for extent */
6372  switch (extenttype) {
6373  case ET_FIRST:
6374  i = 0;
6375  case ET_SECOND:
6376  if (i > 1)
6377  i = 1;
6378 
6379  if (
6380  _isempty[i] && (
6381  (extenttype == ET_FIRST && i == 0) ||
6382  (extenttype == ET_SECOND && i == 1)
6383  )
6384  ) {
6385  elog(NOTICE, "The %s raster is NULL. Returning NULL", (i != 1 ? "FIRST" : "SECOND"));
6386  for (k = 0; k < set_count; k++) {
6387  if (_rast[k] != NULL)
6388  rt_raster_destroy(_rast[k]);
6389  if (pgrastpos[k] != -1)
6390  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6391  }
6392  rt_raster_destroy(raster);
6393  PG_RETURN_NULL();
6394  }
6395 
6396  /* specified band not found */
6397  if (!rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
6398  elog(NOTICE, "The %s raster does not have the band at index %d. Returning no band raster of correct extent",
6399  (i != 1 ? "FIRST" : "SECOND"), bandindex[i]
6400  );
6401 
6402  for (k = 0; k < set_count; k++) {
6403  if (_rast[k] != NULL)
6404  rt_raster_destroy(_rast[k]);
6405  if (pgrastpos[k] != -1)
6406  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6407  }
6408 
6409  pgrtn = rt_raster_serialize(raster);
6410  rt_raster_destroy(raster);
6411  if (!pgrtn) PG_RETURN_NULL();
6412 
6413  SET_VARSIZE(pgrtn, pgrtn->size);
6414  PG_RETURN_POINTER(pgrtn);
6415  }
6416  break;
6417  case ET_UNION:
6418  break;
6419  case ET_INTERSECTION:
6420  /* no intersection */
6421  if (
6422  _isempty[0] || _isempty[1] ||
6423  !dim[0] || !dim[1]
6424  ) {
6425  elog(NOTICE, "The two rasters provided have no intersection. Returning no band raster");
6426 
6427  /* raster has dimension, replace with no band raster */
6428  if (dim[0] || dim[1]) {
6429  rt_raster_destroy(raster);
6430 
6431  raster = rt_raster_new(0, 0);
6432  if (raster == NULL) {
6433  for (k = 0; k < set_count; k++) {
6434  if (_rast[k] != NULL)
6435  rt_raster_destroy(_rast[k]);
6436  if (pgrastpos[k] != -1)
6437  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6438  }
6439  elog(ERROR, "RASTER_mapAlgebra2: Could not create no band raster");
6440  PG_RETURN_NULL();
6441  }
6442 
6443  rt_raster_set_scale(raster, 0, 0);
6444  rt_raster_set_srid(raster, rt_raster_get_srid(_rast[0]));
6445  }
6446 
6447  for (k = 0; k < set_count; k++) {
6448  if (_rast[k] != NULL)
6449  rt_raster_destroy(_rast[k]);
6450  if (pgrastpos[k] != -1)
6451  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6452  }
6453 
6454  pgrtn = rt_raster_serialize(raster);
6455  rt_raster_destroy(raster);
6456  if (!pgrtn) PG_RETURN_NULL();
6457 
6458  SET_VARSIZE(pgrtn, pgrtn->size);
6459  PG_RETURN_POINTER(pgrtn);
6460  }
6461  break;
6462  case ET_LAST:
6463  case ET_CUSTOM:
6464  for (k = 0; k < set_count; k++) {
6465  if (_rast[k] != NULL)
6466  rt_raster_destroy(_rast[k]);
6467  if (pgrastpos[k] != -1)
6468  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6469  }
6470  elog(ERROR, "RASTER_mapAlgebra2: ET_LAST and ET_CUSTOM are not implemented");
6471  PG_RETURN_NULL();
6472  break;
6473  }
6474 
6475  /* both rasters do not have specified bands */
6476  if (
6477  (!_isempty[0] && !rt_raster_has_band(_rast[0], bandindex[0] - 1)) &&
6478  (!_isempty[1] && !rt_raster_has_band(_rast[1], bandindex[1] - 1))
6479  ) {
6480  elog(NOTICE, "The two rasters provided do not have the respectively specified band indices. Returning no band raster of correct extent");
6481 
6482  for (k = 0; k < set_count; k++) {
6483  if (_rast[k] != NULL)
6484  rt_raster_destroy(_rast[k]);
6485  if (pgrastpos[k] != -1)
6486  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6487  }
6488 
6489  pgrtn = rt_raster_serialize(raster);
6490  rt_raster_destroy(raster);
6491  if (!pgrtn) PG_RETURN_NULL();
6492 
6493  SET_VARSIZE(pgrtn, pgrtn->size);
6494  PG_RETURN_POINTER(pgrtn);
6495  }
6496 
6497  /* get bands */
6498  for (i = 0; i < set_count; i++) {
6499  if (_isempty[i] || !rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
6500  _hasnodata[i] = 1;
6501  _nodataval[i] = 0;
6502 
6503  continue;
6504  }
6505 
6506  _band[i] = rt_raster_get_band(_rast[i], bandindex[i] - 1);
6507  if (_band[i] == NULL) {
6508  for (k = 0; k < set_count; k++) {
6509  if (_rast[k] != NULL)
6510  rt_raster_destroy(_rast[k]);
6511  if (pgrastpos[k] != -1)
6512  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6513  }
6514  rt_raster_destroy(raster);
6515  elog(ERROR, "RASTER_mapAlgebra2: Could not get band %d of the %s raster",
6516  bandindex[i],
6517  (i < 1 ? "FIRST" : "SECOND")
6518  );
6519  PG_RETURN_NULL();
6520  }
6521 
6522  _hasnodata[i] = rt_band_get_hasnodata_flag(_band[i]);
6523  if (_hasnodata[i])
6524  rt_band_get_nodata(_band[i], &(_nodataval[i]));
6525  }
6526 
6527  /* pixtype is PT_END, get pixtype based upon extent */
6528  if (pixtype == PT_END) {
6529  if ((extenttype == ET_SECOND && !_isempty[1]) || _isempty[0])
6530  pixtype = rt_band_get_pixtype(_band[1]);
6531  else
6532  pixtype = rt_band_get_pixtype(_band[0]);
6533  }
6534 
6535  /* nodata value for new band */
6536  if (extenttype == ET_SECOND && !_isempty[1] && _hasnodata[1]) {
6537  nodataval = _nodataval[1];
6538  }
6539  else if (!_isempty[0] && _hasnodata[0]) {
6540  nodataval = _nodataval[0];
6541  }
6542  else if (!_isempty[1] && _hasnodata[1]) {
6543  nodataval = _nodataval[1];
6544  }
6545  else {
6546  elog(NOTICE, "Neither raster provided has a NODATA value for the specified band indices. NODATA value set to minimum possible for %s", rt_pixtype_name(pixtype));
6547  nodataval = rt_pixtype_get_min_value(pixtype);
6548  }
6549 
6550  /* add band to output raster */
6552  raster,
6553  pixtype,
6554  nodataval,
6555  1, nodataval,
6556  0
6557  ) < 0) {
6558  for (k = 0; k < set_count; k++) {
6559  if (_rast[k] != NULL)
6560  rt_raster_destroy(_rast[k]);
6561  if (pgrastpos[k] != -1)
6562  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6563  }
6564  rt_raster_destroy(raster);
6565  elog(ERROR, "RASTER_mapAlgebra2: Could not add new band to output raster");
6566  PG_RETURN_NULL();
6567  }
6568 
6569  /* get output band */
6570  band = rt_raster_get_band(raster, 0);
6571  if (band == NULL) {
6572  for (k = 0; k < set_count; k++) {
6573  if (_rast[k] != NULL)
6574  rt_raster_destroy(_rast[k]);
6575  if (pgrastpos[k] != -1)
6576  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6577  }
6578  rt_raster_destroy(raster);
6579  elog(ERROR, "RASTER_mapAlgebra2: Could not get newly added band of output raster");
6580  PG_RETURN_NULL();
6581  }
6582 
6583  POSTGIS_RT_DEBUGF(4, "offsets = (%d, %d, %d, %d)",
6584  (int) _rastoffset[0][0],
6585  (int) _rastoffset[0][1],
6586  (int) _rastoffset[1][0],
6587  (int) _rastoffset[1][1]
6588  );
6589 
6590  POSTGIS_RT_DEBUGF(4, "metadata = (%f, %f, %d, %d, %f, %f, %f, %f, %d)",
6591  rt_raster_get_x_offset(raster),
6592  rt_raster_get_y_offset(raster),
6593  rt_raster_get_width(raster),
6594  rt_raster_get_height(raster),
6595  rt_raster_get_x_scale(raster),
6596  rt_raster_get_y_scale(raster),
6597  rt_raster_get_x_skew(raster),
6598  rt_raster_get_y_skew(raster),
6599  rt_raster_get_srid(raster)
6600  );
6601 
6602  /*
6603  determine who called this function
6604  Arg 4 will either be text or regprocedure
6605  */
6606  POSTGIS_RT_DEBUG(3, "checking parameter type for arg 4");
6607  calltype = get_fn_expr_argtype(fcinfo->flinfo, 4);
6608 
6609  switch(calltype) {
6610  case TEXTOID: {
6611  POSTGIS_RT_DEBUG(3, "arg 4 is \"expression\"!");
6612 
6613  /* connect SPI */
6614  if (SPI_connect() != SPI_OK_CONNECT) {
6615  for (k = 0; k < set_count; k++) {
6616  if (_rast[k] != NULL)
6617  rt_raster_destroy(_rast[k]);
6618  if (pgrastpos[k] != -1)
6619  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6620  }
6621  rt_raster_destroy(raster);
6622  elog(ERROR, "RASTER_mapAlgebra2: Could not connect to the SPI manager");
6623  PG_RETURN_NULL();
6624  }
6625 
6626  /* reset hasargval */
6627  memset(hasargval, 0, sizeof(int) * spi_count);
6628 
6629  /*
6630  process expressions
6631 
6632  spi_exprpos elements are:
6633  4 - expression => spi_plan[0]
6634  7 - nodata1expr => spi_plan[1]
6635  8 - nodata2expr => spi_plan[2]
6636  */
6637  for (i = 0; i < spi_count; i++) {
6638  if (!PG_ARGISNULL(spi_exprpos[i])) {
6639  char *tmp = NULL;
6640  char place[5] = "$1";
6641  expr = text_to_cstring(PG_GETARG_TEXT_P(spi_exprpos[i]));
6642  POSTGIS_RT_DEBUGF(3, "raw expr #%d: %s", i, expr);
6643 
6644  for (j = 0, k = 1; j < ARGKWCOUNT; j++) {
6645  /* attempt to replace keyword with placeholder */
6646  len = 0;
6647  tmp = rtpg_strreplace(expr, argkw[j], place, &len);
6648  pfree(expr);
6649  expr = tmp;
6650 
6651  if (len) {
6652  spi_argcount[i]++;
6653  argpos[i][j] = k++;
6654 
6655  sprintf(place, "$%d", k);
6656  }
6657  else
6658  argpos[i][j] = 0;
6659  }
6660 
6661  len = strlen("SELECT (") + strlen(expr) + strlen(")::double precision");
6662  sql = (char *) palloc(len + 1);
6663  if (sql == NULL) {
6664 
6665  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6666  SPI_finish();
6667 
6668  for (k = 0; k < set_count; k++) {
6669  if (_rast[k] != NULL)
6670  rt_raster_destroy(_rast[k]);
6671  if (pgrastpos[k] != -1)
6672  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6673  }
6674  rt_raster_destroy(raster);
6675 
6676  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for expression parameter %d", spi_exprpos[i]);
6677  PG_RETURN_NULL();
6678  }
6679 
6680  strncpy(sql, "SELECT (", strlen("SELECT ("));
6681  strncpy(sql + strlen("SELECT ("), expr, strlen(expr));
6682  strncpy(sql + strlen("SELECT (") + strlen(expr), ")::double precision", strlen(")::double precision"));
6683  sql[len] = '\0';
6684 
6685  POSTGIS_RT_DEBUGF(3, "sql #%d: %s", i, sql);
6686 
6687  /* create prepared plan */
6688  if (spi_argcount[i]) {
6689  argtype = (Oid *) palloc(spi_argcount[i] * sizeof(Oid));
6690  if (argtype == NULL) {
6691 
6692  pfree(sql);
6693  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6694  SPI_finish();
6695 
6696  for (k = 0; k < set_count; k++) {
6697  if (_rast[k] != NULL)
6698  rt_raster_destroy(_rast[k]);
6699  if (pgrastpos[k] != -1)
6700  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6701  }
6702  rt_raster_destroy(raster);
6703 
6704  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for prepared plan argtypes of expression parameter %d", spi_exprpos[i]);
6705  PG_RETURN_NULL();
6706  }
6707 
6708  /* specify datatypes of parameters */
6709  for (j = 0, k = 0; j < ARGKWCOUNT; j++) {
6710  if (argpos[i][j] < 1) continue;
6711 
6712  /* positions are INT4 */
6713  if (
6714  (strstr(argkw[j], "[rast1.x]") != NULL) ||
6715  (strstr(argkw[j], "[rast1.y]") != NULL) ||
6716  (strstr(argkw[j], "[rast2.x]") != NULL) ||
6717  (strstr(argkw[j], "[rast2.y]") != NULL)
6718  ) {
6719  argtype[k] = INT4OID;
6720  }
6721  /* everything else is FLOAT8 */
6722  else {
6723  argtype[k] = FLOAT8OID;
6724  }
6725 
6726  k++;
6727  }
6728 
6729  spi_plan[i] = SPI_prepare(sql, spi_argcount[i], argtype);
6730  pfree(argtype);
6731 
6732  if (spi_plan[i] == NULL) {
6733 
6734  pfree(sql);
6735  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6736  SPI_finish();
6737 
6738  for (k = 0; k < set_count; k++) {
6739  if (_rast[k] != NULL)
6740  rt_raster_destroy(_rast[k]);
6741  if (pgrastpos[k] != -1)
6742  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6743  }
6744  rt_raster_destroy(raster);
6745 
6746  elog(ERROR, "RASTER_mapAlgebra2: Could not create prepared plan of expression parameter %d", spi_exprpos[i]);
6747  PG_RETURN_NULL();
6748  }
6749  }
6750  /* no args, just execute query */
6751  else {
6752  err = SPI_execute(sql, TRUE, 0);
6753  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
6754 
6755  pfree(sql);
6756  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6757  SPI_finish();
6758 
6759  for (k = 0; k < set_count; k++) {
6760  if (_rast[k] != NULL)
6761  rt_raster_destroy(_rast[k]);
6762  if (pgrastpos[k] != -1)
6763  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6764  }
6765  rt_raster_destroy(raster);
6766 
6767  elog(ERROR, "RASTER_mapAlgebra2: Could not evaluate expression parameter %d", spi_exprpos[i]);
6768  PG_RETURN_NULL();
6769  }
6770 
6771  /* get output of prepared plan */
6772  tupdesc = SPI_tuptable->tupdesc;
6773  tuptable = SPI_tuptable;
6774  tuple = tuptable->vals[0];
6775 
6776  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
6777  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
6778 
6779  pfree(sql);
6780  if (SPI_tuptable) SPI_freetuptable(tuptable);
6781  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6782  SPI_finish();
6783 
6784  for (k = 0; k < set_count; k++) {
6785  if (_rast[k] != NULL)
6786  rt_raster_destroy(_rast[k]);
6787  if (pgrastpos[k] != -1)
6788  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6789  }
6790  rt_raster_destroy(raster);
6791 
6792  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of expression parameter %d", spi_exprpos[i]);
6793  PG_RETURN_NULL();
6794  }
6795 
6796  if (!isnull) {
6797  hasargval[i] = 1;
6798  argval[i] = DatumGetFloat8(datum);
6799  }
6800 
6801  if (SPI_tuptable) SPI_freetuptable(tuptable);
6802  }
6803 
6804  pfree(sql);
6805  }
6806  else
6807  spi_empty++;
6808  }
6809 
6810  /* nodatanodataval */
6811  if (!PG_ARGISNULL(9)) {
6812  hasnodatanodataval = 1;
6813  nodatanodataval = PG_GETARG_FLOAT8(9);
6814  }
6815  else
6816  hasnodatanodataval = 0;
6817  break;
6818  }
6819  case REGPROCEDUREOID: {
6820  POSTGIS_RT_DEBUG(3, "arg 4 is \"userfunction\"!");
6821  if (!PG_ARGISNULL(4)) {
6822 
6823  ufc_nullcount = 0;
6824  ufc_noid = PG_GETARG_OID(4);
6825 
6826  /* get function info */
6827  fmgr_info(ufc_noid, &ufl_info);
6828 
6829  /* function cannot return set */
6830  err = 0;
6831  if (ufl_info.fn_retset) {
6832  err = 1;
6833  }
6834  /* function should have correct # of args */
6835  else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) {
6836  err = 2;
6837  }
6838 
6839  /*
6840  TODO: consider adding checks of the userfunction parameters
6841  should be able to use get_fn_expr_argtype() of fmgr.c
6842  */
6843 
6844  if (err > 0) {
6845  for (k = 0; k < set_count; k++) {
6846  if (_rast[k] != NULL)
6847  rt_raster_destroy(_rast[k]);
6848  if (pgrastpos[k] != -1)
6849  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6850  }
6851  rt_raster_destroy(raster);
6852 
6853  if (err > 1)
6854  elog(ERROR, "RASTER_mapAlgebra2: Function provided must have three or four input parameters");
6855  else
6856  elog(ERROR, "RASTER_mapAlgebra2: Function provided must return double precision not resultset");
6857  PG_RETURN_NULL();
6858  }
6859 
6860  if (func_volatile(ufc_noid) == 'v') {
6861  elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
6862  }
6863 
6864  /* prep function call data */
6865 #if POSTGIS_PGSQL_VERSION <= 90
6866  InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL);
6867 #else
6868  InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
6869 #endif
6870  memset(ufc_info.argnull, FALSE, sizeof(bool) * ufl_info.fn_nargs);
6871 
6872  if (ufl_info.fn_nargs != 4)
6873  k = 2;
6874  else
6875  k = 3;
6876  if (!PG_ARGISNULL(7)) {
6877  ufc_info.arg[k] = PG_GETARG_DATUM(7);
6878  }
6879  else {
6880  ufc_info.arg[k] = (Datum) NULL;
6881  ufc_info.argnull[k] = TRUE;
6882  ufc_nullcount++;
6883  }
6884  }
6885  break;
6886  }
6887  default:
6888  for (k = 0; k < set_count; k++) {
6889  if (_rast[k] != NULL)
6890  rt_raster_destroy(_rast[k]);
6891  if (pgrastpos[k] != -1)
6892  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6893  }
6894  rt_raster_destroy(raster);
6895  elog(ERROR, "RASTER_mapAlgebra2: Invalid data type for expression or userfunction");
6896  PG_RETURN_NULL();
6897  break;
6898  }
6899 
6900  /* loop over pixels */
6901  /* if any expression present, run */
6902  if ((
6903  (calltype == TEXTOID) && (
6904  (spi_empty != spi_count) || hasnodatanodataval
6905  )
6906  ) || (
6907  (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid)
6908  )) {
6909  for (x = 0; x < dim[0]; x++) {
6910  for (y = 0; y < dim[1]; y++) {
6911 
6912  /* get pixel from each raster */
6913  for (i = 0; i < set_count; i++) {
6914  _haspixel[i] = 0;
6915  _pixel[i] = 0;
6916 
6917  /* row/column */
6918  _x = x - (int) _rastoffset[i][0];
6919  _y = y - (int) _rastoffset[i][1];
6920 
6921  /* store _x and _y in 1-based */
6922  _pos[i][0] = _x + 1;
6923  _pos[i][1] = _y + 1;
6924 
6925  /* get pixel value */
6926  if (_band[i] == NULL) {
6927  if (!_hasnodata[i]) {
6928  _haspixel[i] = 1;
6929  _pixel[i] = _nodataval[i];
6930  }
6931  }
6932  else if (
6933  !_isempty[i] &&
6934  (_x >= 0 && _x < _dim[i][0]) &&
6935  (_y >= 0 && _y < _dim[i][1])
6936  ) {
6937  err = rt_band_get_pixel(_band[i], _x, _y, &(_pixel[i]), &isnodata);
6938  if (err != ES_NONE) {
6939 
6940  if (calltype == TEXTOID) {
6941  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6942  SPI_finish();
6943  }
6944 
6945  for (k = 0; k < set_count; k++) {
6946  if (_rast[k] != NULL)
6947  rt_raster_destroy(_rast[k]);
6948  if (pgrastpos[k] != -1)
6949  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6950  }
6951  rt_raster_destroy(raster);
6952 
6953  elog(ERROR, "RASTER_mapAlgebra2: Could not get pixel of %s raster", (i < 1 ? "FIRST" : "SECOND"));
6954  PG_RETURN_NULL();
6955  }
6956 
6957  if (!_hasnodata[i] || !isnodata)
6958  _haspixel[i] = 1;
6959  }
6960 
6961  POSTGIS_RT_DEBUGF(5, "pixel r%d(%d, %d) = %d, %f",
6962  i,
6963  _x, _y,
6964  _haspixel[i],
6965  _pixel[i]
6966  );
6967  }
6968 
6969  haspixel = 0;
6970 
6971  switch (calltype) {
6972  case TEXTOID: {
6973  /* which prepared plan to use? */
6974  /* !pixel0 && !pixel1 */
6975  /* use nodatanodataval */
6976  if (!_haspixel[0] && !_haspixel[1])
6977  i = 3;
6978  /* pixel0 && !pixel1 */
6979  /* run spi_plan[2] (nodata2expr) */
6980  else if (_haspixel[0] && !_haspixel[1])
6981  i = 2;
6982  /* !pixel0 && pixel1 */
6983  /* run spi_plan[1] (nodata1expr) */
6984  else if (!_haspixel[0] && _haspixel[1])
6985  i = 1;
6986  /* pixel0 && pixel1 */
6987  /* run spi_plan[0] (expression) */
6988  else
6989  i = 0;
6990 
6991  /* process values */
6992  if (i == 3) {
6993  if (hasnodatanodataval) {
6994  haspixel = 1;
6995  pixel = nodatanodataval;
6996  }
6997  }
6998  /* has an evaluated value */
6999  else if (hasargval[i]) {
7000  haspixel = 1;
7001  pixel = argval[i];
7002  }
7003  /* prepared plan exists */
7004  else if (spi_plan[i] != NULL) {
7005  POSTGIS_RT_DEBUGF(4, "Using prepared plan: %d", i);
7006 
7007  /* reset values to (Datum) NULL */
7008  memset(values, (Datum) NULL, sizeof(Datum) * ARGKWCOUNT);
7009  /* reset nulls to FALSE */
7010  memset(nulls, FALSE, sizeof(char) * ARGKWCOUNT);
7011 
7012  /* expression has argument(s) */
7013  if (spi_argcount[i]) {
7014  /* set values and nulls */
7015  for (j = 0; j < ARGKWCOUNT; j++) {
7016  idx = argpos[i][j];
7017  if (idx < 1) continue;
7018  idx--; /* 1-based becomes 0-based */
7019 
7020  if (strstr(argkw[j], "[rast1.x]") != NULL) {
7021  values[idx] = _pos[0][0];
7022  }
7023  else if (strstr(argkw[j], "[rast1.y]") != NULL) {
7024  values[idx] = _pos[0][1];
7025  }
7026  else if (
7027  (strstr(argkw[j], "[rast1.val]") != NULL) ||
7028  (strstr(argkw[j], "[rast1]") != NULL)
7029  ) {
7030  if (_isempty[0] || !_haspixel[0])
7031  nulls[idx] = TRUE;
7032  else
7033  values[idx] = Float8GetDatum(_pixel[0]);
7034  }
7035  else if (strstr(argkw[j], "[rast2.x]") != NULL) {
7036  values[idx] = _pos[1][0];
7037  }
7038  else if (strstr(argkw[j], "[rast2.y]") != NULL) {
7039  values[idx] = _pos[1][1];
7040  }
7041  else if (
7042  (strstr(argkw[j], "[rast2.val]") != NULL) ||
7043  (strstr(argkw[j], "[rast2]") != NULL)
7044  ) {
7045  if (_isempty[1] || !_haspixel[1])
7046  nulls[idx] = TRUE;
7047  else
7048  values[idx] = Float8GetDatum(_pixel[1]);
7049  }
7050  }
7051  }
7052 
7053  /* run prepared plan */
7054  err = SPI_execute_plan(spi_plan[i], values, nulls, TRUE, 1);
7055  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
7056 
7057  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7058  SPI_finish();
7059 
7060  for (k = 0; k < set_count; k++) {
7061  if (_rast[k] != NULL)
7062  rt_raster_destroy(_rast[k]);
7063  if (pgrastpos[k] != -1)
7064  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7065  }
7066  rt_raster_destroy(raster);
7067 
7068  elog(ERROR, "RASTER_mapAlgebra2: Unexpected error when running prepared statement %d", i);
7069  PG_RETURN_NULL();
7070  }
7071 
7072  /* get output of prepared plan */
7073  tupdesc = SPI_tuptable->tupdesc;
7074  tuptable = SPI_tuptable;
7075  tuple = tuptable->vals[0];
7076 
7077  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
7078  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
7079 
7080  if (SPI_tuptable) SPI_freetuptable(tuptable);
7081  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7082  SPI_finish();
7083 
7084  for (k = 0; k < set_count; k++) {
7085  if (_rast[k] != NULL)
7086  rt_raster_destroy(_rast[k]);
7087  if (pgrastpos[k] != -1)
7088  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7089  }
7090  rt_raster_destroy(raster);
7091 
7092  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of prepared statement %d", i);
7093  PG_RETURN_NULL();
7094  }
7095 
7096  if (!isnull) {
7097  haspixel = 1;
7098  pixel = DatumGetFloat8(datum);
7099  }
7100 
7101  if (SPI_tuptable) SPI_freetuptable(tuptable);
7102  }
7103  } break;
7104  case REGPROCEDUREOID: {
7105  Datum d[4];
7106  ArrayType *a;
7107 
7108  /* build fcnarg */
7109  for (i = 0; i < set_count; i++) {
7110  ufc_info.arg[i] = Float8GetDatum(_pixel[i]);
7111 
7112  if (_haspixel[i]) {
7113  ufc_info.argnull[i] = FALSE;
7114  ufc_nullcount--;
7115  }
7116  else {
7117  ufc_info.argnull[i] = TRUE;
7118  ufc_nullcount++;
7119  }
7120  }
7121 
7122  /* function is strict and null parameter is passed */
7123  /* http://archives.postgresql.org/pgsql-general/2011-11/msg00424.php */
7124  if (ufl_info.fn_strict && ufc_nullcount)
7125  break;
7126 
7127  /* 4 parameters, add position */
7128  if (ufl_info.fn_nargs == 4) {
7129  /* Datum of 4 element array */
7130  /* array is (x1, y1, x2, y2) */
7131  for (i = 0; i < set_count; i++) {
7132  if (i < 1) {
7133  d[0] = Int32GetDatum(_pos[i][0]);
7134  d[1] = Int32GetDatum(_pos[i][1]);
7135  }
7136  else {
7137  d[2] = Int32GetDatum(_pos[i][0]);
7138  d[3] = Int32GetDatum(_pos[i][1]);
7139  }
7140  }
7141 
7142  a = construct_array(d, 4, INT4OID, sizeof(int32), true, 'i');
7143  ufc_info.arg[2] = PointerGetDatum(a);
7144  ufc_info.argnull[2] = FALSE;
7145  }
7146 
7147  datum = FunctionCallInvoke(&ufc_info);
7148 
7149  /* result is not null*/
7150  if (!ufc_info.isnull) {
7151  haspixel = 1;
7152  pixel = DatumGetFloat8(datum);
7153  }
7154  } break;
7155  }
7156 
7157  /* burn pixel if haspixel != 0 */
7158  if (haspixel) {
7159  if (rt_band_set_pixel(band, x, y, pixel, NULL) != ES_NONE) {
7160 
7161  if (calltype == TEXTOID) {
7162  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7163  SPI_finish();
7164  }
7165 
7166  for (k = 0; k < set_count; k++) {
7167  if (_rast[k] != NULL)
7168  rt_raster_destroy(_rast[k]);
7169  if (pgrastpos[k] != -1)
7170  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7171  }
7172  rt_raster_destroy(raster);
7173 
7174  elog(ERROR, "RASTER_mapAlgebra2: Could not set pixel value of output raster");
7175  PG_RETURN_NULL();
7176  }
7177  }
7178 
7179  POSTGIS_RT_DEBUGF(5, "(x, y, val) = (%d, %d, %f)", x, y, haspixel ? pixel : nodataval);
7180 
7181  } /* y: height */
7182  } /* x: width */
7183  }
7184 
7185  /* CLEANUP */
7186  if (calltype == TEXTOID) {
7187  for (i = 0; i < spi_count; i++) {
7188  if (spi_plan[i] != NULL) SPI_freeplan(spi_plan[i]);
7189  }
7190  SPI_finish();
7191  }
7192 
7193  for (k = 0; k < set_count; k++) {
7194  if (_rast[k] != NULL)
7195  rt_raster_destroy(_rast[k]);
7196  if (pgrastpos[k] != -1)
7197  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7198  }
7199 
7200  pgrtn = rt_raster_serialize(raster);
7201  rt_raster_destroy(raster);
7202  if (!pgrtn) PG_RETURN_NULL();
7203 
7204  POSTGIS_RT_DEBUG(3, "Finished RASTER_mapAlgebra2");
7205 
7206  SET_VARSIZE(pgrtn, pgrtn->size);
7207  PG_RETURN_POINTER(pgrtn);
7208 }
char * text_to_cstring(const text *textptr)
unsigned int int32
Definition: shpopen.c:273
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition: rt_raster.c:213
pixel
Definition: pixval.py:90
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition: rt_raster.c:190
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
raster
Be careful!! Zeros function&#39;s input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster&#39;s geotransform using 6-element array.
Definition: rt_raster.c:727
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_raster.c:706
char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
Definition: rtpg_internal.c:55
band
Definition: ovdump.py:57
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
Definition: rt_raster.c:3461
rt_extenttype
Definition: librtcore.h:200
gt
Definition: window.py:77
rt_pixtype
Definition: librtcore.h:185
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_raster.c:1334
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rtpostgis.h:65
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1730
unsigned int uint32_t
Definition: uthash.h:78
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1221
rt_extenttype rt_util_extent_type(const char *name)
Definition: rt_util.c:191
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
Definition: rt_raster.c:137
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
Definition: rt_raster.c:485
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition: rt_pixel.c:80
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:381
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:674
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition: rt_raster.c:150
char * rtpg_trim(const char *input)
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
Definition: rt_raster.c:1347
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:148
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster&#39;s SRID.
Definition: rt_raster.c:363
int32_t rt_raster_get_srid(rt_raster raster)
Get raster&#39;s SRID.
Definition: rt_raster.c:356
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition: rt_raster.c:159
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_raster.c:48
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition: rt_raster.c:181
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_raster.c:121
#define FALSE
Definition: dbfopen.c:168
Struct definitions.
Definition: librtcore.h:2250
#define ARGKWCOUNT
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:631
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel&#39;s value.
Definition: rt_band.c:974
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_raster.c:129
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
unsigned char uint8_t
Definition: uthash.h:79
#define TRUE
Definition: dbfopen.c:169
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:725
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
Definition: rt_raster.c:222
char * rtpg_strtoupper(char *str)
Here is the call graph for this function: