PostGIS  2.5.0beta2dev-r@@SVN_REVISION@@

◆ RASTER_mapAlgebra2()

Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6077 of file rtpg_mapalgebra.c.

References 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.

Referenced by RASTER_mapAlgebraFctNgb().

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