PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ RASTER_mapAlgebra2()

Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6225 of file rtpg_mapalgebra.c.

6226 {
6227  const uint32_t set_count = 2;
6228  rt_pgraster *pgrast[2] = { NULL, NULL };
6229  int pgrastpos[2] = {-1, -1};
6230  rt_pgraster *pgrtn;
6231  rt_raster rast[2] = {NULL};
6232  int _isempty[2] = {0};
6233  uint32_t bandindex[2] = {0};
6234  rt_raster _rast[2] = {NULL};
6235  rt_band _band[2] = {NULL};
6236  int _hasnodata[2] = {0};
6237  double _nodataval[2] = {0};
6238  double _offset[4] = {0.};
6239  double _rastoffset[2][4] = {{0.}};
6240  int _haspixel[2] = {0};
6241  double _pixel[2] = {0};
6242  int _pos[2][2] = {{0}};
6243  uint16_t _dim[2][2] = {{0}};
6244 
6245  char *pixtypename = NULL;
6246  rt_pixtype pixtype = PT_END;
6247  char *extenttypename = NULL;
6248  rt_extenttype extenttype = ET_INTERSECTION;
6249 
6250  rt_raster raster = NULL;
6251  rt_band band = NULL;
6252  uint16_t dim[2] = {0};
6253  int haspixel = 0;
6254  double pixel = 0.;
6255  double nodataval = 0;
6256  double gt[6] = {0.};
6257 
6258  Oid calltype = InvalidOid;
6259 
6260  const uint32_t spi_count = 3;
6261  uint16_t spi_exprpos[3] = {4, 7, 8};
6262  uint32_t spi_argcount[3] = {0};
6263  char *expr = NULL;
6264  char *sql = NULL;
6265  SPIPlanPtr spi_plan[3] = {NULL};
6266  uint16_t spi_empty = 0;
6267  Oid *argtype = NULL;
6268  uint8_t argpos[3][8] = {{0}};
6269  char *argkw[] = {"[rast1.x]", "[rast1.y]", "[rast1.val]", "[rast1]", "[rast2.x]", "[rast2.y]", "[rast2.val]", "[rast2]"};
6270  Datum values[ARGKWCOUNT];
6271  char nulls[ARGKWCOUNT];
6272  TupleDesc tupdesc;
6273  SPITupleTable *tuptable = NULL;
6274  HeapTuple tuple;
6275  Datum datum;
6276  bool isnull = FALSE;
6277  int hasargval[3] = {0};
6278  double argval[3] = {0.};
6279  int hasnodatanodataval = 0;
6280  double nodatanodataval = 0;
6281  int isnodata = 0;
6282 
6283  Oid ufc_noid = InvalidOid;
6284  FmgrInfo ufl_info;
6285 #if POSTGIS_PGSQL_VERSION < 120
6286  FunctionCallInfoData ufc_info;
6287 #else
6288  LOCAL_FCINFO(ufc_info, FUNC_MAX_ARGS); /* Could be optimized */
6289 #endif
6290  int ufc_nullcount = 0;
6291 
6292  int idx = 0;
6293  uint32_t i = 0;
6294  uint32_t j = 0;
6295  uint32_t k = 0;
6296  uint32_t x = 0;
6297  uint32_t y = 0;
6298  int _x = 0;
6299  int _y = 0;
6300  int err;
6301  int aligned = 0;
6302  int len = 0;
6303 
6304  POSTGIS_RT_DEBUG(3, "Starting RASTER_mapAlgebra2");
6305 
6306  for (i = 0, j = 0; i < set_count; i++) {
6307  if (!PG_ARGISNULL(j)) {
6308  pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
6309  pgrastpos[i] = j;
6310  j++;
6311 
6312  /* raster */
6313  rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
6314  if (!rast[i]) {
6315  for (k = 0; k <= i; k++) {
6316  if (k < i && rast[k] != NULL)
6317  rt_raster_destroy(rast[k]);
6318  if (pgrastpos[k] != -1)
6319  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6320  }
6321  elog(ERROR, "RASTER_mapAlgebra2: Could not deserialize the %s raster", i < 1 ? "first" : "second");
6322  PG_RETURN_NULL();
6323  }
6324 
6325  /* empty */
6326  _isempty[i] = rt_raster_is_empty(rast[i]);
6327 
6328  /* band index */
6329  if (!PG_ARGISNULL(j)) {
6330  bandindex[i] = PG_GETARG_INT32(j);
6331  }
6332  j++;
6333  }
6334  else {
6335  _isempty[i] = 1;
6336  j += 2;
6337  }
6338 
6339  POSTGIS_RT_DEBUGF(3, "_isempty[%d] = %d", i, _isempty[i]);
6340  }
6341 
6342  /* both rasters are NULL */
6343  if (rast[0] == NULL && rast[1] == NULL) {
6344  elog(NOTICE, "The two rasters provided are NULL. Returning NULL");
6345  for (k = 0; k < set_count; k++) {
6346  if (pgrastpos[k] != -1)
6347  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6348  }
6349  PG_RETURN_NULL();
6350  }
6351 
6352  /* both rasters are empty */
6353  if (_isempty[0] && _isempty[1]) {
6354  elog(NOTICE, "The two rasters provided are empty. Returning empty raster");
6355 
6356  raster = rt_raster_new(0, 0);
6357  if (raster == NULL) {
6358  for (k = 0; k < set_count; k++) {
6359  if (rast[k] != NULL)
6360  rt_raster_destroy(rast[k]);
6361  if (pgrastpos[k] != -1)
6362  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6363  }
6364  elog(ERROR, "RASTER_mapAlgebra2: Could not create empty raster");
6365  PG_RETURN_NULL();
6366  }
6367  rt_raster_set_scale(raster, 0, 0);
6368 
6369  pgrtn = rt_raster_serialize(raster);
6371  if (!pgrtn)
6372  PG_RETURN_NULL();
6373 
6374  SET_VARSIZE(pgrtn, pgrtn->size);
6375  PG_RETURN_POINTER(pgrtn);
6376  }
6377 
6378  /* replace the empty or NULL raster with one matching the other */
6379  if (
6380  (rast[0] == NULL || _isempty[0]) ||
6381  (rast[1] == NULL || _isempty[1])
6382  ) {
6383  /* first raster is empty */
6384  if (rast[0] == NULL || _isempty[0]) {
6385  i = 0;
6386  j = 1;
6387  }
6388  /* second raster is empty */
6389  else {
6390  i = 1;
6391  j = 0;
6392  }
6393 
6394  _rast[j] = rast[j];
6395 
6396  /* raster is empty, destroy it */
6397  if (_rast[i] != NULL)
6398  rt_raster_destroy(_rast[i]);
6399 
6400  _dim[i][0] = rt_raster_get_width(_rast[j]);
6401  _dim[i][1] = rt_raster_get_height(_rast[j]);
6402  _dim[j][0] = rt_raster_get_width(_rast[j]);
6403  _dim[j][1] = rt_raster_get_height(_rast[j]);
6404 
6405  _rast[i] = rt_raster_new(
6406  _dim[j][0],
6407  _dim[j][1]
6408  );
6409  if (_rast[i] == NULL) {
6410  rt_raster_destroy(_rast[j]);
6411  for (k = 0; k < set_count; k++) {
6412  if (pgrastpos[k] != -1)
6413  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6414  }
6415  elog(ERROR, "RASTER_mapAlgebra2: Could not create NODATA raster");
6416  PG_RETURN_NULL();
6417  }
6418  rt_raster_set_srid(_rast[i], rt_raster_get_srid(_rast[j]));
6419 
6422  }
6423  else {
6424  _rast[0] = rast[0];
6425  _dim[0][0] = rt_raster_get_width(_rast[0]);
6426  _dim[0][1] = rt_raster_get_height(_rast[0]);
6427 
6428  _rast[1] = rast[1];
6429  _dim[1][0] = rt_raster_get_width(_rast[1]);
6430  _dim[1][1] = rt_raster_get_height(_rast[1]);
6431  }
6432 
6433  /* SRID must match */
6434  /*
6435  if (rt_raster_get_srid(_rast[0]) != rt_raster_get_srid(_rast[1])) {
6436  elog(NOTICE, "The two rasters provided have different SRIDs. Returning NULL");
6437  for (k = 0; k < set_count; k++) {
6438  if (_rast[k] != NULL)
6439  rt_raster_destroy(_rast[k]);
6440  if (pgrastpos[k] != -1)
6441  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6442  }
6443  PG_RETURN_NULL();
6444  }
6445  */
6446 
6447  /* same alignment */
6448  if (rt_raster_same_alignment(_rast[0], _rast[1], &aligned, NULL) != ES_NONE) {
6449  for (k = 0; k < set_count; k++) {
6450  if (_rast[k] != NULL)
6451  rt_raster_destroy(_rast[k]);
6452  if (pgrastpos[k] != -1)
6453  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6454  }
6455  elog(ERROR, "RASTER_mapAlgebra2: Could not test for alignment on the two rasters");
6456  PG_RETURN_NULL();
6457  }
6458  if (!aligned) {
6459  elog(NOTICE, "The two rasters provided do not have the same alignment. Returning NULL");
6460  for (k = 0; k < set_count; k++) {
6461  if (_rast[k] != NULL)
6462  rt_raster_destroy(_rast[k]);
6463  if (pgrastpos[k] != -1)
6464  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6465  }
6466  PG_RETURN_NULL();
6467  }
6468 
6469  /* pixel type */
6470  if (!PG_ARGISNULL(5)) {
6471  pixtypename = text_to_cstring(PG_GETARG_TEXT_P(5));
6472  /* Get the pixel type index */
6473  pixtype = rt_pixtype_index_from_name(pixtypename);
6474  if (pixtype == PT_END ) {
6475  for (k = 0; k < set_count; k++) {
6476  if (_rast[k] != NULL)
6477  rt_raster_destroy(_rast[k]);
6478  if (pgrastpos[k] != -1)
6479  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6480  }
6481  elog(ERROR, "RASTER_mapAlgebra2: Invalid pixel type: %s", pixtypename);
6482  PG_RETURN_NULL();
6483  }
6484  }
6485 
6486  /* extent type */
6487  if (!PG_ARGISNULL(6)) {
6488  extenttypename = rtpg_strtoupper(rtpg_trim(text_to_cstring(PG_GETARG_TEXT_P(6))));
6489  extenttype = rt_util_extent_type(extenttypename);
6490  }
6491  POSTGIS_RT_DEBUGF(3, "extenttype: %d %s", extenttype, extenttypename);
6492 
6493  /* computed raster from extent type */
6495  _rast[0], _rast[1],
6496  extenttype,
6497  &raster, _offset
6498  );
6499  if (err != ES_NONE) {
6500  for (k = 0; k < set_count; k++) {
6501  if (_rast[k] != NULL)
6502  rt_raster_destroy(_rast[k]);
6503  if (pgrastpos[k] != -1)
6504  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6505  }
6506  elog(ERROR, "RASTER_mapAlgebra2: Could not get output raster of correct extent");
6507  PG_RETURN_NULL();
6508  }
6509 
6510  /* copy offsets */
6511  _rastoffset[0][0] = _offset[0];
6512  _rastoffset[0][1] = _offset[1];
6513  _rastoffset[1][0] = _offset[2];
6514  _rastoffset[1][1] = _offset[3];
6515 
6516  /* get output raster dimensions */
6517  dim[0] = rt_raster_get_width(raster);
6518  dim[1] = rt_raster_get_height(raster);
6519 
6520  i = 2;
6521  /* handle special cases for extent */
6522  switch (extenttype) {
6523  case ET_FIRST:
6524  i = 0;
6525  /* fall through */
6526  case ET_SECOND:
6527  if (i > 1)
6528  i = 1;
6529 
6530  if (
6531  _isempty[i] && (
6532  (extenttype == ET_FIRST && i == 0) ||
6533  (extenttype == ET_SECOND && i == 1)
6534  )
6535  ) {
6536  elog(NOTICE, "The %s raster is NULL. Returning NULL", (i != 1 ? "FIRST" : "SECOND"));
6537  for (k = 0; k < set_count; k++) {
6538  if (_rast[k] != NULL)
6539  rt_raster_destroy(_rast[k]);
6540  if (pgrastpos[k] != -1)
6541  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6542  }
6544  PG_RETURN_NULL();
6545  }
6546 
6547  /* specified band not found */
6548  if (!rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
6549  elog(NOTICE, "The %s raster does not have the band at index %d. Returning no band raster of correct extent",
6550  (i != 1 ? "FIRST" : "SECOND"), bandindex[i]
6551  );
6552 
6553  for (k = 0; k < set_count; k++) {
6554  if (_rast[k] != NULL)
6555  rt_raster_destroy(_rast[k]);
6556  if (pgrastpos[k] != -1)
6557  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6558  }
6559 
6560  pgrtn = rt_raster_serialize(raster);
6562  if (!pgrtn) PG_RETURN_NULL();
6563 
6564  SET_VARSIZE(pgrtn, pgrtn->size);
6565  PG_RETURN_POINTER(pgrtn);
6566  }
6567  break;
6568  case ET_UNION:
6569  break;
6570  case ET_INTERSECTION:
6571  /* no intersection */
6572  if (
6573  _isempty[0] || _isempty[1] ||
6574  !dim[0] || !dim[1]
6575  ) {
6576  elog(NOTICE, "The two rasters provided have no intersection. Returning no band raster");
6577 
6578  /* raster has dimension, replace with no band raster */
6579  if (dim[0] || dim[1]) {
6581 
6582  raster = rt_raster_new(0, 0);
6583  if (raster == NULL) {
6584  for (k = 0; k < set_count; k++) {
6585  if (_rast[k] != NULL)
6586  rt_raster_destroy(_rast[k]);
6587  if (pgrastpos[k] != -1)
6588  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6589  }
6590  elog(ERROR, "RASTER_mapAlgebra2: Could not create no band raster");
6591  PG_RETURN_NULL();
6592  }
6593 
6594  rt_raster_set_scale(raster, 0, 0);
6596  }
6597 
6598  for (k = 0; k < set_count; k++) {
6599  if (_rast[k] != NULL)
6600  rt_raster_destroy(_rast[k]);
6601  if (pgrastpos[k] != -1)
6602  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6603  }
6604 
6605  pgrtn = rt_raster_serialize(raster);
6607  if (!pgrtn) PG_RETURN_NULL();
6608 
6609  SET_VARSIZE(pgrtn, pgrtn->size);
6610  PG_RETURN_POINTER(pgrtn);
6611  }
6612  break;
6613  case ET_LAST:
6614  case ET_CUSTOM:
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  elog(ERROR, "RASTER_mapAlgebra2: ET_LAST and ET_CUSTOM are not implemented");
6622  PG_RETURN_NULL();
6623  break;
6624  }
6625 
6626  /* both rasters do not have specified bands */
6627  if (
6628  (!_isempty[0] && !rt_raster_has_band(_rast[0], bandindex[0] - 1)) &&
6629  (!_isempty[1] && !rt_raster_has_band(_rast[1], bandindex[1] - 1))
6630  ) {
6631  elog(NOTICE, "The two rasters provided do not have the respectively specified band indices. Returning no band raster of correct extent");
6632 
6633  for (k = 0; k < set_count; k++) {
6634  if (_rast[k] != NULL)
6635  rt_raster_destroy(_rast[k]);
6636  if (pgrastpos[k] != -1)
6637  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6638  }
6639 
6640  pgrtn = rt_raster_serialize(raster);
6642  if (!pgrtn) PG_RETURN_NULL();
6643 
6644  SET_VARSIZE(pgrtn, pgrtn->size);
6645  PG_RETURN_POINTER(pgrtn);
6646  }
6647 
6648  /* get bands */
6649  for (i = 0; i < set_count; i++) {
6650  if (_isempty[i] || !rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
6651  _hasnodata[i] = 1;
6652  _nodataval[i] = 0;
6653 
6654  continue;
6655  }
6656 
6657  _band[i] = rt_raster_get_band(_rast[i], bandindex[i] - 1);
6658  if (_band[i] == NULL) {
6659  for (k = 0; k < set_count; k++) {
6660  if (_rast[k] != NULL)
6661  rt_raster_destroy(_rast[k]);
6662  if (pgrastpos[k] != -1)
6663  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6664  }
6666  elog(ERROR, "RASTER_mapAlgebra2: Could not get band %d of the %s raster",
6667  bandindex[i],
6668  (i < 1 ? "FIRST" : "SECOND")
6669  );
6670  PG_RETURN_NULL();
6671  }
6672 
6673  _hasnodata[i] = rt_band_get_hasnodata_flag(_band[i]);
6674  if (_hasnodata[i])
6675  rt_band_get_nodata(_band[i], &(_nodataval[i]));
6676  }
6677 
6678  /* pixtype is PT_END, get pixtype based upon extent */
6679  if (pixtype == PT_END) {
6680  if ((extenttype == ET_SECOND && !_isempty[1]) || _isempty[0])
6681  pixtype = rt_band_get_pixtype(_band[1]);
6682  else
6683  pixtype = rt_band_get_pixtype(_band[0]);
6684  }
6685 
6686  /* nodata value for new band */
6687  if (extenttype == ET_SECOND && !_isempty[1] && _hasnodata[1]) {
6688  nodataval = _nodataval[1];
6689  }
6690  else if (!_isempty[0] && _hasnodata[0]) {
6691  nodataval = _nodataval[0];
6692  }
6693  else if (!_isempty[1] && _hasnodata[1]) {
6694  nodataval = _nodataval[1];
6695  }
6696  else {
6697  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));
6698  nodataval = rt_pixtype_get_min_value(pixtype);
6699  }
6700 
6701  /* add band to output raster */
6703  raster,
6704  pixtype,
6705  nodataval,
6706  1, nodataval,
6707  0
6708  ) < 0) {
6709  for (k = 0; k < set_count; k++) {
6710  if (_rast[k] != NULL)
6711  rt_raster_destroy(_rast[k]);
6712  if (pgrastpos[k] != -1)
6713  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6714  }
6716  elog(ERROR, "RASTER_mapAlgebra2: Could not add new band to output raster");
6717  PG_RETURN_NULL();
6718  }
6719 
6720  /* get output band */
6722  if (band == NULL) {
6723  for (k = 0; k < set_count; k++) {
6724  if (_rast[k] != NULL)
6725  rt_raster_destroy(_rast[k]);
6726  if (pgrastpos[k] != -1)
6727  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6728  }
6730  elog(ERROR, "RASTER_mapAlgebra2: Could not get newly added band of output raster");
6731  PG_RETURN_NULL();
6732  }
6733 
6734  POSTGIS_RT_DEBUGF(4, "offsets = (%d, %d, %d, %d)",
6735  (int) _rastoffset[0][0],
6736  (int) _rastoffset[0][1],
6737  (int) _rastoffset[1][0],
6738  (int) _rastoffset[1][1]
6739  );
6740 
6741  POSTGIS_RT_DEBUGF(4, "metadata = (%f, %f, %d, %d, %f, %f, %f, %f, %d)",
6751  );
6752 
6753  /*
6754  determine who called this function
6755  Arg 4 will either be text or regprocedure
6756  */
6757  POSTGIS_RT_DEBUG(3, "checking parameter type for arg 4");
6758  calltype = get_fn_expr_argtype(fcinfo->flinfo, 4);
6759 
6760  switch(calltype) {
6761  case TEXTOID: {
6762  POSTGIS_RT_DEBUG(3, "arg 4 is \"expression\"!");
6763 
6764  /* connect SPI */
6765  if (SPI_connect() != SPI_OK_CONNECT) {
6766  for (k = 0; k < set_count; k++) {
6767  if (_rast[k] != NULL)
6768  rt_raster_destroy(_rast[k]);
6769  if (pgrastpos[k] != -1)
6770  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6771  }
6773  elog(ERROR, "RASTER_mapAlgebra2: Could not connect to the SPI manager");
6774  PG_RETURN_NULL();
6775  }
6776 
6777  /* reset hasargval */
6778  memset(hasargval, 0, sizeof(int) * spi_count);
6779 
6780  /*
6781  process expressions
6782 
6783  spi_exprpos elements are:
6784  4 - expression => spi_plan[0]
6785  7 - nodata1expr => spi_plan[1]
6786  8 - nodata2expr => spi_plan[2]
6787  */
6788  for (i = 0; i < spi_count; i++) {
6789  if (!PG_ARGISNULL(spi_exprpos[i])) {
6790  char *tmp = NULL;
6791  char place[5] = "$1";
6792  expr = text_to_cstring(PG_GETARG_TEXT_P(spi_exprpos[i]));
6793  POSTGIS_RT_DEBUGF(3, "raw expr #%d: %s", i, expr);
6794 
6795  for (j = 0, k = 1; j < ARGKWCOUNT; j++) {
6796  /* attempt to replace keyword with placeholder */
6797  len = 0;
6798  tmp = rtpg_strreplace(expr, argkw[j], place, &len);
6799  pfree(expr);
6800  expr = tmp;
6801 
6802  if (len) {
6803  spi_argcount[i]++;
6804  argpos[i][j] = k++;
6805 
6806  sprintf(place, "$%d", k);
6807  }
6808  else
6809  argpos[i][j] = 0;
6810  }
6811 
6812  len = strlen("SELECT (") + strlen(expr) + strlen(")::double precision");
6813  sql = (char *) palloc(len + 1);
6814  if (sql == NULL) {
6815 
6816  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6817  SPI_finish();
6818 
6819  for (k = 0; k < set_count; k++) {
6820  if (_rast[k] != NULL)
6821  rt_raster_destroy(_rast[k]);
6822  if (pgrastpos[k] != -1)
6823  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6824  }
6826 
6827  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for expression parameter %d", spi_exprpos[i]);
6828  PG_RETURN_NULL();
6829  }
6830 
6831  strncpy(sql, "SELECT (", strlen("SELECT ("));
6832  strncpy(sql + strlen("SELECT ("), expr, strlen(expr));
6833  strncpy(sql + strlen("SELECT (") + strlen(expr), ")::double precision", strlen(")::double precision"));
6834  sql[len] = '\0';
6835 
6836  POSTGIS_RT_DEBUGF(3, "sql #%d: %s", i, sql);
6837 
6838  /* create prepared plan */
6839  if (spi_argcount[i]) {
6840  argtype = (Oid *) palloc(spi_argcount[i] * sizeof(Oid));
6841  if (argtype == NULL) {
6842 
6843  pfree(sql);
6844  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6845  SPI_finish();
6846 
6847  for (k = 0; k < set_count; k++) {
6848  if (_rast[k] != NULL)
6849  rt_raster_destroy(_rast[k]);
6850  if (pgrastpos[k] != -1)
6851  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6852  }
6854 
6855  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for prepared plan argtypes of expression parameter %d", spi_exprpos[i]);
6856  PG_RETURN_NULL();
6857  }
6858 
6859  /* specify datatypes of parameters */
6860  for (j = 0, k = 0; j < ARGKWCOUNT; j++) {
6861  if (argpos[i][j] < 1) continue;
6862 
6863  /* positions are INT4 */
6864  if (
6865  (strstr(argkw[j], "[rast1.x]") != NULL) ||
6866  (strstr(argkw[j], "[rast1.y]") != NULL) ||
6867  (strstr(argkw[j], "[rast2.x]") != NULL) ||
6868  (strstr(argkw[j], "[rast2.y]") != NULL)
6869  ) {
6870  argtype[k] = INT4OID;
6871  }
6872  /* everything else is FLOAT8 */
6873  else {
6874  argtype[k] = FLOAT8OID;
6875  }
6876 
6877  k++;
6878  }
6879 
6880  spi_plan[i] = SPI_prepare(sql, spi_argcount[i], argtype);
6881  pfree(argtype);
6882 
6883  if (spi_plan[i] == NULL) {
6884 
6885  pfree(sql);
6886  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6887  SPI_finish();
6888 
6889  for (k = 0; k < set_count; k++) {
6890  if (_rast[k] != NULL)
6891  rt_raster_destroy(_rast[k]);
6892  if (pgrastpos[k] != -1)
6893  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6894  }
6896 
6897  elog(ERROR, "RASTER_mapAlgebra2: Could not create prepared plan of expression parameter %d", spi_exprpos[i]);
6898  PG_RETURN_NULL();
6899  }
6900  }
6901  /* no args, just execute query */
6902  else {
6903  err = SPI_execute(sql, TRUE, 0);
6904  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
6905 
6906  pfree(sql);
6907  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6908  SPI_finish();
6909 
6910  for (k = 0; k < set_count; k++) {
6911  if (_rast[k] != NULL)
6912  rt_raster_destroy(_rast[k]);
6913  if (pgrastpos[k] != -1)
6914  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6915  }
6917 
6918  elog(ERROR, "RASTER_mapAlgebra2: Could not evaluate expression parameter %d", spi_exprpos[i]);
6919  PG_RETURN_NULL();
6920  }
6921 
6922  /* get output of prepared plan */
6923  tupdesc = SPI_tuptable->tupdesc;
6924  tuptable = SPI_tuptable;
6925  tuple = tuptable->vals[0];
6926 
6927  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
6928  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
6929 
6930  pfree(sql);
6931  if (SPI_tuptable) SPI_freetuptable(tuptable);
6932  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6933  SPI_finish();
6934 
6935  for (k = 0; k < set_count; k++) {
6936  if (_rast[k] != NULL)
6937  rt_raster_destroy(_rast[k]);
6938  if (pgrastpos[k] != -1)
6939  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6940  }
6942 
6943  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of expression parameter %d", spi_exprpos[i]);
6944  PG_RETURN_NULL();
6945  }
6946 
6947  if (!isnull) {
6948  hasargval[i] = 1;
6949  argval[i] = DatumGetFloat8(datum);
6950  }
6951 
6952  if (SPI_tuptable) SPI_freetuptable(tuptable);
6953  }
6954 
6955  pfree(sql);
6956  }
6957  else
6958  spi_empty++;
6959  }
6960 
6961  /* nodatanodataval */
6962  if (!PG_ARGISNULL(9)) {
6963  hasnodatanodataval = 1;
6964  nodatanodataval = PG_GETARG_FLOAT8(9);
6965  }
6966  else
6967  hasnodatanodataval = 0;
6968  break;
6969  }
6970  case REGPROCEDUREOID: {
6971  POSTGIS_RT_DEBUG(3, "arg 4 is \"userfunction\"!");
6972  if (!PG_ARGISNULL(4)) {
6973 
6974  ufc_nullcount = 0;
6975  ufc_noid = PG_GETARG_OID(4);
6976 
6977  /* get function info */
6978  fmgr_info(ufc_noid, &ufl_info);
6979 
6980  /* function cannot return set */
6981  err = 0;
6982  if (ufl_info.fn_retset) {
6983  err = 1;
6984  }
6985  /* function should have correct # of args */
6986  else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) {
6987  err = 2;
6988  }
6989 
6990  /*
6991  TODO: consider adding checks of the userfunction parameters
6992  should be able to use get_fn_expr_argtype() of fmgr.c
6993  */
6994 
6995  if (err > 0) {
6996  for (k = 0; k < set_count; k++) {
6997  if (_rast[k] != NULL)
6998  rt_raster_destroy(_rast[k]);
6999  if (pgrastpos[k] != -1)
7000  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7001  }
7003 
7004  if (err > 1)
7005  elog(ERROR, "RASTER_mapAlgebra2: Function provided must have three or four input parameters");
7006  else
7007  elog(ERROR, "RASTER_mapAlgebra2: Function provided must return double precision not resultset");
7008  PG_RETURN_NULL();
7009  }
7010 
7011  if (func_volatile(ufc_noid) == 'v') {
7012  elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
7013  }
7014 
7015  /* prep function call data */
7016 #if POSTGIS_PGSQL_VERSION < 120
7017  InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7018  memset(ufc_info.argnull, FALSE, sizeof(bool) * ufl_info.fn_nargs);
7019 #else
7020  InitFunctionCallInfoData(
7021  *ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7022  ufc_info->args[0].isnull = FALSE;
7023  ufc_info->args[1].isnull = FALSE;
7024  ufc_info->args[2].isnull = FALSE;
7025  if (ufl_info.fn_nargs == 4)
7026  ufc_info->args[3].isnull = FALSE;
7027 #endif
7028 
7029  if (ufl_info.fn_nargs != 4)
7030  k = 2;
7031  else
7032  k = 3;
7033 #if POSTGIS_PGSQL_VERSION < 120
7034  if (!PG_ARGISNULL(7)) {
7035  ufc_info.arg[k] = PG_GETARG_DATUM(7);
7036  }
7037  else {
7038  ufc_info.arg[k] = (Datum) NULL;
7039  ufc_info.argnull[k] = TRUE;
7040  ufc_nullcount++;
7041  }
7042 #else
7043  if (!PG_ARGISNULL(7))
7044  {
7045  ufc_info->args[k].value = PG_GETARG_DATUM(7);
7046  }
7047  else
7048  {
7049  ufc_info->args[k].value = (Datum)NULL;
7050  ufc_info->args[k].isnull = TRUE;
7051  ufc_nullcount++;
7052  }
7053 #endif
7054  }
7055  break;
7056  }
7057  default:
7058  for (k = 0; k < set_count; k++) {
7059  if (_rast[k] != NULL)
7060  rt_raster_destroy(_rast[k]);
7061  if (pgrastpos[k] != -1)
7062  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7063  }
7065  elog(ERROR, "RASTER_mapAlgebra2: Invalid data type for expression or userfunction");
7066  PG_RETURN_NULL();
7067  break;
7068  }
7069 
7070  /* loop over pixels */
7071  /* if any expression present, run */
7072  if ((
7073  (calltype == TEXTOID) && (
7074  (spi_empty != spi_count) || hasnodatanodataval
7075  )
7076  ) || (
7077  (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid)
7078  )) {
7079  for (x = 0; x < dim[0]; x++) {
7080  for (y = 0; y < dim[1]; y++) {
7081 
7082  /* get pixel from each raster */
7083  for (i = 0; i < set_count; i++) {
7084  _haspixel[i] = 0;
7085  _pixel[i] = 0;
7086 
7087  /* row/column */
7088  _x = x - (int) _rastoffset[i][0];
7089  _y = y - (int) _rastoffset[i][1];
7090 
7091  /* store _x and _y in 1-based */
7092  _pos[i][0] = _x + 1;
7093  _pos[i][1] = _y + 1;
7094 
7095  /* get pixel value */
7096  if (_band[i] == NULL) {
7097  if (!_hasnodata[i]) {
7098  _haspixel[i] = 1;
7099  _pixel[i] = _nodataval[i];
7100  }
7101  }
7102  else if (
7103  !_isempty[i] &&
7104  (_x >= 0 && _x < _dim[i][0]) &&
7105  (_y >= 0 && _y < _dim[i][1])
7106  ) {
7107  err = rt_band_get_pixel(_band[i], _x, _y, &(_pixel[i]), &isnodata);
7108  if (err != ES_NONE) {
7109 
7110  if (calltype == TEXTOID) {
7111  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7112  SPI_finish();
7113  }
7114 
7115  for (k = 0; k < set_count; k++) {
7116  if (_rast[k] != NULL)
7117  rt_raster_destroy(_rast[k]);
7118  if (pgrastpos[k] != -1)
7119  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7120  }
7122 
7123  elog(ERROR, "RASTER_mapAlgebra2: Could not get pixel of %s raster", (i < 1 ? "FIRST" : "SECOND"));
7124  PG_RETURN_NULL();
7125  }
7126 
7127  if (!_hasnodata[i] || !isnodata)
7128  _haspixel[i] = 1;
7129  }
7130 
7131  POSTGIS_RT_DEBUGF(5, "pixel r%d(%d, %d) = %d, %f",
7132  i,
7133  _x, _y,
7134  _haspixel[i],
7135  _pixel[i]
7136  );
7137  }
7138 
7139  haspixel = 0;
7140 
7141  switch (calltype) {
7142  case TEXTOID: {
7143  /* which prepared plan to use? */
7144  /* !pixel0 && !pixel1 */
7145  /* use nodatanodataval */
7146  if (!_haspixel[0] && !_haspixel[1])
7147  i = 3;
7148  /* pixel0 && !pixel1 */
7149  /* run spi_plan[2] (nodata2expr) */
7150  else if (_haspixel[0] && !_haspixel[1])
7151  i = 2;
7152  /* !pixel0 && pixel1 */
7153  /* run spi_plan[1] (nodata1expr) */
7154  else if (!_haspixel[0] && _haspixel[1])
7155  i = 1;
7156  /* pixel0 && pixel1 */
7157  /* run spi_plan[0] (expression) */
7158  else
7159  i = 0;
7160 
7161  /* process values */
7162  if (i == 3) {
7163  if (hasnodatanodataval) {
7164  haspixel = 1;
7165  pixel = nodatanodataval;
7166  }
7167  }
7168  /* has an evaluated value */
7169  else if (hasargval[i]) {
7170  haspixel = 1;
7171  pixel = argval[i];
7172  }
7173  /* prepared plan exists */
7174  else if (spi_plan[i] != NULL) {
7175  POSTGIS_RT_DEBUGF(4, "Using prepared plan: %d", i);
7176 
7177  /* reset values to (Datum) NULL */
7178  memset(values, (Datum) NULL, sizeof(Datum) * ARGKWCOUNT);
7179  /* reset nulls to FALSE */
7180  memset(nulls, FALSE, sizeof(char) * ARGKWCOUNT);
7181 
7182  /* expression has argument(s) */
7183  if (spi_argcount[i]) {
7184  /* set values and nulls */
7185  for (j = 0; j < ARGKWCOUNT; j++) {
7186  idx = argpos[i][j];
7187  if (idx < 1) continue;
7188  idx--; /* 1-based becomes 0-based */
7189 
7190  if (strstr(argkw[j], "[rast1.x]") != NULL) {
7191  values[idx] = _pos[0][0];
7192  }
7193  else if (strstr(argkw[j], "[rast1.y]") != NULL) {
7194  values[idx] = _pos[0][1];
7195  }
7196  else if (
7197  (strstr(argkw[j], "[rast1.val]") != NULL) ||
7198  (strstr(argkw[j], "[rast1]") != NULL)
7199  ) {
7200  if (_isempty[0] || !_haspixel[0])
7201  nulls[idx] = TRUE;
7202  else
7203  values[idx] = Float8GetDatum(_pixel[0]);
7204  }
7205  else if (strstr(argkw[j], "[rast2.x]") != NULL) {
7206  values[idx] = _pos[1][0];
7207  }
7208  else if (strstr(argkw[j], "[rast2.y]") != NULL) {
7209  values[idx] = _pos[1][1];
7210  }
7211  else if (
7212  (strstr(argkw[j], "[rast2.val]") != NULL) ||
7213  (strstr(argkw[j], "[rast2]") != NULL)
7214  ) {
7215  if (_isempty[1] || !_haspixel[1])
7216  nulls[idx] = TRUE;
7217  else
7218  values[idx] = Float8GetDatum(_pixel[1]);
7219  }
7220  }
7221  }
7222 
7223  /* run prepared plan */
7224  err = SPI_execute_plan(spi_plan[i], values, nulls, TRUE, 1);
7225  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
7226 
7227  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7228  SPI_finish();
7229 
7230  for (k = 0; k < set_count; k++) {
7231  if (_rast[k] != NULL)
7232  rt_raster_destroy(_rast[k]);
7233  if (pgrastpos[k] != -1)
7234  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7235  }
7237 
7238  elog(ERROR, "RASTER_mapAlgebra2: Unexpected error when running prepared statement %d", i);
7239  PG_RETURN_NULL();
7240  }
7241 
7242  /* get output of prepared plan */
7243  tupdesc = SPI_tuptable->tupdesc;
7244  tuptable = SPI_tuptable;
7245  tuple = tuptable->vals[0];
7246 
7247  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
7248  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
7249 
7250  if (SPI_tuptable) SPI_freetuptable(tuptable);
7251  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7252  SPI_finish();
7253 
7254  for (k = 0; k < set_count; k++) {
7255  if (_rast[k] != NULL)
7256  rt_raster_destroy(_rast[k]);
7257  if (pgrastpos[k] != -1)
7258  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7259  }
7261 
7262  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of prepared statement %d", i);
7263  PG_RETURN_NULL();
7264  }
7265 
7266  if (!isnull) {
7267  haspixel = 1;
7268  pixel = DatumGetFloat8(datum);
7269  }
7270 
7271  if (SPI_tuptable) SPI_freetuptable(tuptable);
7272  }
7273  } break;
7274  case REGPROCEDUREOID: {
7275  Datum d[4];
7276  ArrayType *a;
7277 
7278  /* build fcnarg */
7279  for (i = 0; i < set_count; i++) {
7280 #if POSTGIS_PGSQL_VERSION < 120
7281  ufc_info.arg[i] = Float8GetDatum(_pixel[i]);
7282 #else
7283  ufc_info->args[i].value = Float8GetDatum(_pixel[i]);
7284 #endif
7285 
7286  if (_haspixel[i]) {
7287 #if POSTGIS_PGSQL_VERSION < 120
7288  ufc_info.argnull[i] = FALSE;
7289 #else
7290  ufc_info->args[i].isnull = FALSE;
7291 #endif
7292  ufc_nullcount--;
7293  }
7294  else {
7295 #if POSTGIS_PGSQL_VERSION < 120
7296  ufc_info.argnull[i] = TRUE;
7297 #else
7298  ufc_info->args[i].isnull = TRUE;
7299 #endif
7300  ufc_nullcount++;
7301  }
7302  }
7303 
7304  /* function is strict and null parameter is passed */
7305  /* http://archives.postgresql.org/pgsql-general/2011-11/msg00424.php */
7306  if (ufl_info.fn_strict && ufc_nullcount)
7307  break;
7308 
7309  /* 4 parameters, add position */
7310  if (ufl_info.fn_nargs == 4) {
7311  /* Datum of 4 element array */
7312  /* array is (x1, y1, x2, y2) */
7313  for (i = 0; i < set_count; i++) {
7314  if (i < 1) {
7315  d[0] = Int32GetDatum(_pos[i][0]);
7316  d[1] = Int32GetDatum(_pos[i][1]);
7317  }
7318  else {
7319  d[2] = Int32GetDatum(_pos[i][0]);
7320  d[3] = Int32GetDatum(_pos[i][1]);
7321  }
7322  }
7323 
7324  a = construct_array(d, 4, INT4OID, sizeof(int32), true, 'i');
7325 #if POSTGIS_PGSQL_VERSION < 120
7326  ufc_info.arg[2] = PointerGetDatum(a);
7327  ufc_info.argnull[2] = FALSE;
7328 #else
7329  ufc_info->args[2].value = PointerGetDatum(a);
7330  ufc_info->args[2].isnull = FALSE;
7331 #endif
7332  }
7333 
7334 #if POSTGIS_PGSQL_VERSION < 120
7335  datum = FunctionCallInvoke(&ufc_info);
7336 
7337  /* result is not null*/
7338  if (!ufc_info.isnull) {
7339  haspixel = 1;
7340  pixel = DatumGetFloat8(datum);
7341  }
7342 #else
7343  datum = FunctionCallInvoke(ufc_info);
7344 
7345  /* result is not null*/
7346  if (!ufc_info->isnull)
7347  {
7348  haspixel = 1;
7349  pixel = DatumGetFloat8(datum);
7350  }
7351 #endif
7352  } break;
7353  }
7354 
7355  /* burn pixel if haspixel != 0 */
7356  if (haspixel) {
7357  if (rt_band_set_pixel(band, x, y, pixel, NULL) != ES_NONE) {
7358 
7359  if (calltype == TEXTOID) {
7360  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7361  SPI_finish();
7362  }
7363 
7364  for (k = 0; k < set_count; k++) {
7365  if (_rast[k] != NULL)
7366  rt_raster_destroy(_rast[k]);
7367  if (pgrastpos[k] != -1)
7368  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7369  }
7371 
7372  elog(ERROR, "RASTER_mapAlgebra2: Could not set pixel value of output raster");
7373  PG_RETURN_NULL();
7374  }
7375  }
7376 
7377  POSTGIS_RT_DEBUGF(5, "(x, y, val) = (%d, %d, %f)", x, y, haspixel ? pixel : nodataval);
7378 
7379  } /* y: height */
7380  } /* x: width */
7381  }
7382 
7383  /* CLEANUP */
7384  if (calltype == TEXTOID) {
7385  for (i = 0; i < spi_count; i++) {
7386  if (spi_plan[i] != NULL) SPI_freeplan(spi_plan[i]);
7387  }
7388  SPI_finish();
7389  }
7390 
7391  for (k = 0; k < set_count; k++) {
7392  if (_rast[k] != NULL)
7393  rt_raster_destroy(_rast[k]);
7394  if (pgrastpos[k] != -1)
7395  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7396  }
7397 
7398  pgrtn = rt_raster_serialize(raster);
7400  if (!pgrtn) PG_RETURN_NULL();
7401 
7402  POSTGIS_RT_DEBUG(3, "Finished RASTER_mapAlgebra2");
7403 
7404  SET_VARSIZE(pgrtn, pgrtn->size);
7405  PG_RETURN_POINTER(pgrtn);
7406 }
#define TRUE
Definition: dbfopen.c:169
#define FALSE
Definition: dbfopen.c:168
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition: rt_raster.c:356
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition: rt_raster.c:181
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition: rt_raster.c:213
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
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
Definition: rt_raster.c:727
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
Definition: rt_raster.c:137
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:674
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition: rt_pixel.c:80
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
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
rt_pixtype
Definition: librtcore.h:185
@ PT_END
Definition: librtcore.h:197
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_raster.c:48
rt_extenttype rt_util_extent_type(const char *name)
Definition: rt_util.c:191
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:148
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
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition: rt_raster.c:150
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
Definition: rt_band.c:974
@ ES_NONE
Definition: librtcore.h:180
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_raster.c:129
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition: rt_raster.c:363
rt_extenttype
Definition: librtcore.h:200
@ ET_CUSTOM
Definition: librtcore.h:206
@ ET_LAST
Definition: librtcore.h:205
@ ET_INTERSECTION
Definition: librtcore.h:201
@ ET_UNION
Definition: librtcore.h:202
@ ET_SECOND
Definition: librtcore.h:204
@ ET_FIRST
Definition: librtcore.h:203
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1730
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:631
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_raster.c:121
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:3361
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition: rt_raster.c:159
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition: rt_raster.c:190
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_raster.c:706
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
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_raster.c:1334
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:381
band
Definition: ovdump.py:57
pixel
Definition: pixval.py:90
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
gt
Definition: window.py:77
char * text_to_cstring(const text *textptr)
char * rtpg_strtoupper(char *str)
char * rtpg_trim(const char *input)
char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
Definition: rtpg_internal.c:55
#define ARGKWCOUNT
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rtpostgis.h:65
unsigned int int32
Definition: shpopen.c:273
Struct definitions.
Definition: librtcore.h:2250
unsigned int uint32_t
Definition: uthash.h:78
unsigned char uint8_t
Definition: uthash.h:79

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.

Here is the call graph for this function: