PostGIS  2.3.7dev-r@@SVN_REVISION@@
Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6083 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, TRUE, pixval::x, and pixval::y.

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

Here is the call graph for this function: