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

Definition at line 14554 of file rt_pg.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.

14555 {
14556  const int set_count = 2;
14557  rt_pgraster *pgrast[2];
14558  int pgrastpos[2] = {-1, -1};
14559  rt_pgraster *pgrtn;
14560  rt_raster rast[2] = {NULL};
14561  int _isempty[2] = {0};
14562  uint32_t bandindex[2] = {0};
14563  rt_raster _rast[2] = {NULL};
14564  rt_band _band[2] = {NULL};
14565  int _hasnodata[2] = {0};
14566  double _nodataval[2] = {0};
14567  double _offset[4] = {0.};
14568  double _rastoffset[2][4] = {{0.}};
14569  int _haspixel[2] = {0};
14570  double _pixel[2] = {0};
14571  int _pos[2][2] = {{0}};
14572  uint16_t _dim[2][2] = {{0}};
14573 
14574  char *pixtypename = NULL;
14575  rt_pixtype pixtype = PT_END;
14576  char *extenttypename = NULL;
14577  rt_extenttype extenttype = ET_INTERSECTION;
14578 
14579  rt_raster raster = NULL;
14580  rt_band band = NULL;
14581  uint16_t dim[2] = {0};
14582  int haspixel = 0;
14583  double pixel = 0.;
14584  double nodataval = 0;
14585  double gt[6] = {0.};
14586 
14587  Oid calltype = InvalidOid;
14588 
14589  const int spi_count = 3;
14590  uint16_t spi_exprpos[3] = {4, 7, 8};
14591  uint32_t spi_argcount[3] = {0};
14592  char *expr = NULL;
14593  char *sql = NULL;
14594  SPIPlanPtr spi_plan[3] = {NULL};
14595  uint16_t spi_empty = 0;
14596  Oid *argtype = NULL;
14597  const int argkwcount = 8;
14598  uint8_t argpos[3][8] = {{0}};
14599  char *argkw[] = {"[rast1.x]", "[rast1.y]", "[rast1.val]", "[rast1]", "[rast2.x]", "[rast2.y]", "[rast2.val]", "[rast2]"};
14600  Datum values[argkwcount];
14601  bool nulls[argkwcount];
14602  TupleDesc tupdesc;
14603  SPITupleTable *tuptable = NULL;
14604  HeapTuple tuple;
14605  Datum datum;
14606  bool isnull = FALSE;
14607  int hasargval[3] = {0};
14608  double argval[3] = {0.};
14609  int hasnodatanodataval = 0;
14610  double nodatanodataval = 0;
14611  int isnodata = 0;
14612 
14613  Oid ufc_noid = InvalidOid;
14614  FmgrInfo ufl_info;
14615  FunctionCallInfoData ufc_info;
14616  int ufc_nullcount = 0;
14617 
14618  int idx = 0;
14619  uint32_t i = 0;
14620  uint32_t j = 0;
14621  uint32_t k = 0;
14622  uint32_t x = 0;
14623  uint32_t y = 0;
14624  int _x = 0;
14625  int _y = 0;
14626  int err;
14627  int aligned = 0;
14628  int len = 0;
14629 
14630  POSTGIS_RT_DEBUG(3, "Starting RASTER_mapAlgebra2");
14631 
14632  for (i = 0, j = 0; i < set_count; i++) {
14633  if (!PG_ARGISNULL(j)) {
14634  pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
14635  pgrastpos[i] = j;
14636  j++;
14637 
14638  /* raster */
14639  rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
14640  if (!rast[i]) {
14641  for (k = 0; k <= i; k++) {
14642  if (k < i && rast[k] != NULL)
14643  rt_raster_destroy(rast[k]);
14644  if (pgrastpos[k] != -1)
14645  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14646  }
14647  elog(ERROR, "RASTER_mapAlgebra2: Could not deserialize the %s raster", i < 1 ? "first" : "second");
14648  PG_RETURN_NULL();
14649  }
14650 
14651  /* empty */
14652  _isempty[i] = rt_raster_is_empty(rast[i]);
14653 
14654  /* band index */
14655  if (!PG_ARGISNULL(j)) {
14656  bandindex[i] = PG_GETARG_INT32(j);
14657  }
14658  j++;
14659  }
14660  else {
14661  _isempty[i] = 1;
14662  j += 2;
14663  }
14664 
14665  POSTGIS_RT_DEBUGF(3, "_isempty[%d] = %d", i, _isempty[i]);
14666  }
14667 
14668  /* both rasters are NULL */
14669  if (rast[0] == NULL && rast[1] == NULL) {
14670  elog(NOTICE, "The two rasters provided are NULL. Returning NULL");
14671  for (k = 0; k < set_count; k++) {
14672  if (pgrastpos[k] != -1)
14673  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14674  }
14675  PG_RETURN_NULL();
14676  }
14677 
14678  /* both rasters are empty */
14679  if (_isempty[0] && _isempty[1]) {
14680  elog(NOTICE, "The two rasters provided are empty. Returning empty raster");
14681 
14682  raster = rt_raster_new(0, 0);
14683  if (raster == NULL) {
14684  for (k = 0; k < set_count; k++) {
14685  if (rast[k] != NULL)
14686  rt_raster_destroy(rast[k]);
14687  if (pgrastpos[k] != -1)
14688  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14689  }
14690  elog(ERROR, "RASTER_mapAlgebra2: Could not create empty raster");
14691  PG_RETURN_NULL();
14692  }
14693  rt_raster_set_scale(raster, 0, 0);
14694 
14695  pgrtn = rt_raster_serialize(raster);
14696  rt_raster_destroy(raster);
14697  if (!pgrtn)
14698  PG_RETURN_NULL();
14699 
14700  SET_VARSIZE(pgrtn, pgrtn->size);
14701  PG_RETURN_POINTER(pgrtn);
14702  }
14703 
14704  /* replace the empty or NULL raster with one matching the other */
14705  if (
14706  (rast[0] == NULL || _isempty[0]) ||
14707  (rast[1] == NULL || _isempty[1])
14708  ) {
14709  /* first raster is empty */
14710  if (rast[0] == NULL || _isempty[0]) {
14711  i = 0;
14712  j = 1;
14713  }
14714  /* second raster is empty */
14715  else {
14716  i = 1;
14717  j = 0;
14718  }
14719 
14720  _rast[j] = rast[j];
14721 
14722  /* raster is empty, destroy it */
14723  if (_rast[i] != NULL)
14724  rt_raster_destroy(_rast[i]);
14725 
14726  _dim[i][0] = rt_raster_get_width(_rast[j]);
14727  _dim[i][1] = rt_raster_get_height(_rast[j]);
14728  _dim[j][0] = rt_raster_get_width(_rast[j]);
14729  _dim[j][1] = rt_raster_get_height(_rast[j]);
14730 
14731  _rast[i] = rt_raster_new(
14732  _dim[j][0],
14733  _dim[j][1]
14734  );
14735  if (_rast[i] == NULL) {
14736  rt_raster_destroy(_rast[j]);
14737  for (k = 0; k < set_count; k++) {
14738  if (pgrastpos[k] != -1)
14739  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14740  }
14741  elog(ERROR, "RASTER_mapAlgebra2: Could not create NODATA raster");
14742  PG_RETURN_NULL();
14743  }
14744  rt_raster_set_srid(_rast[i], rt_raster_get_srid(_rast[j]));
14745 
14746  rt_raster_get_geotransform_matrix(_rast[j], gt);
14747  rt_raster_set_geotransform_matrix(_rast[i], gt);
14748  }
14749  else {
14750  _rast[0] = rast[0];
14751  _dim[0][0] = rt_raster_get_width(_rast[0]);
14752  _dim[0][1] = rt_raster_get_height(_rast[0]);
14753 
14754  _rast[1] = rast[1];
14755  _dim[1][0] = rt_raster_get_width(_rast[1]);
14756  _dim[1][1] = rt_raster_get_height(_rast[1]);
14757  }
14758 
14759  /* SRID must match */
14760  /*
14761  if (rt_raster_get_srid(_rast[0]) != rt_raster_get_srid(_rast[1])) {
14762  elog(NOTICE, "The two rasters provided have different SRIDs. Returning NULL");
14763  for (k = 0; k < set_count; k++) {
14764  if (_rast[k] != NULL)
14765  rt_raster_destroy(_rast[k]);
14766  if (pgrastpos[k] != -1)
14767  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14768  }
14769  PG_RETURN_NULL();
14770  }
14771  */
14772 
14773  /* same alignment */
14774  if (rt_raster_same_alignment(_rast[0], _rast[1], &aligned, NULL) != ES_NONE) {
14775  for (k = 0; k < set_count; k++) {
14776  if (_rast[k] != NULL)
14777  rt_raster_destroy(_rast[k]);
14778  if (pgrastpos[k] != -1)
14779  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14780  }
14781  elog(ERROR, "RASTER_mapAlgebra2: Could not test for alignment on the two rasters");
14782  PG_RETURN_NULL();
14783  }
14784  if (!aligned) {
14785  elog(NOTICE, "The two rasters provided do not have the same alignment. Returning NULL");
14786  for (k = 0; k < set_count; k++) {
14787  if (_rast[k] != NULL)
14788  rt_raster_destroy(_rast[k]);
14789  if (pgrastpos[k] != -1)
14790  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14791  }
14792  PG_RETURN_NULL();
14793  }
14794 
14795  /* pixel type */
14796  if (!PG_ARGISNULL(5)) {
14797  pixtypename = text_to_cstring(PG_GETARG_TEXT_P(5));
14798  /* Get the pixel type index */
14799  pixtype = rt_pixtype_index_from_name(pixtypename);
14800  if (pixtype == PT_END ) {
14801  for (k = 0; k < set_count; k++) {
14802  if (_rast[k] != NULL)
14803  rt_raster_destroy(_rast[k]);
14804  if (pgrastpos[k] != -1)
14805  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14806  }
14807  elog(ERROR, "RASTER_mapAlgebra2: Invalid pixel type: %s", pixtypename);
14808  PG_RETURN_NULL();
14809  }
14810  }
14811 
14812  /* extent type */
14813  if (!PG_ARGISNULL(6)) {
14814  extenttypename = rtpg_strtoupper(rtpg_trim(text_to_cstring(PG_GETARG_TEXT_P(6))));
14815  extenttype = rt_util_extent_type(extenttypename);
14816  }
14817  POSTGIS_RT_DEBUGF(3, "extenttype: %d %s", extenttype, extenttypename);
14818 
14819  /* computed raster from extent type */
14821  _rast[0], _rast[1],
14822  extenttype,
14823  &raster, _offset
14824  );
14825  if (err != ES_NONE) {
14826  for (k = 0; k < set_count; k++) {
14827  if (_rast[k] != NULL)
14828  rt_raster_destroy(_rast[k]);
14829  if (pgrastpos[k] != -1)
14830  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14831  }
14832  elog(ERROR, "RASTER_mapAlgebra2: Could not get output raster of correct extent");
14833  PG_RETURN_NULL();
14834  }
14835 
14836  /* copy offsets */
14837  _rastoffset[0][0] = _offset[0];
14838  _rastoffset[0][1] = _offset[1];
14839  _rastoffset[1][0] = _offset[2];
14840  _rastoffset[1][1] = _offset[3];
14841 
14842  /* get output raster dimensions */
14843  dim[0] = rt_raster_get_width(raster);
14844  dim[1] = rt_raster_get_height(raster);
14845 
14846  i = 2;
14847  /* handle special cases for extent */
14848  switch (extenttype) {
14849  case ET_FIRST:
14850  i = 0;
14851  case ET_SECOND:
14852  if (i > 1)
14853  i = 1;
14854 
14855  if (
14856  _isempty[i] && (
14857  (extenttype == ET_FIRST && i == 0) ||
14858  (extenttype == ET_SECOND && i == 1)
14859  )
14860  ) {
14861  elog(NOTICE, "The %s raster is NULL. Returning NULL", (i != 1 ? "FIRST" : "SECOND"));
14862  for (k = 0; k < set_count; k++) {
14863  if (_rast[k] != NULL)
14864  rt_raster_destroy(_rast[k]);
14865  if (pgrastpos[k] != -1)
14866  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14867  }
14868  rt_raster_destroy(raster);
14869  PG_RETURN_NULL();
14870  }
14871 
14872  /* specified band not found */
14873  if (!rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
14874  elog(NOTICE, "The %s raster does not have the band at index %d. Returning no band raster of correct extent",
14875  (i != 1 ? "FIRST" : "SECOND"), bandindex[i]
14876  );
14877 
14878  for (k = 0; k < set_count; k++) {
14879  if (_rast[k] != NULL)
14880  rt_raster_destroy(_rast[k]);
14881  if (pgrastpos[k] != -1)
14882  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14883  }
14884 
14885  pgrtn = rt_raster_serialize(raster);
14886  rt_raster_destroy(raster);
14887  if (!pgrtn) PG_RETURN_NULL();
14888 
14889  SET_VARSIZE(pgrtn, pgrtn->size);
14890  PG_RETURN_POINTER(pgrtn);
14891  }
14892  break;
14893  case ET_UNION:
14894  break;
14895  case ET_INTERSECTION:
14896  /* no intersection */
14897  if (
14898  _isempty[0] || _isempty[1] ||
14899  !dim[0] || !dim[1]
14900  ) {
14901  elog(NOTICE, "The two rasters provided have no intersection. Returning no band raster");
14902 
14903  /* raster has dimension, replace with no band raster */
14904  if (dim[0] || dim[1]) {
14905  rt_raster_destroy(raster);
14906 
14907  raster = rt_raster_new(0, 0);
14908  if (raster == NULL) {
14909  for (k = 0; k < set_count; k++) {
14910  if (_rast[k] != NULL)
14911  rt_raster_destroy(_rast[k]);
14912  if (pgrastpos[k] != -1)
14913  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14914  }
14915  elog(ERROR, "RASTER_mapAlgebra2: Could not create no band raster");
14916  PG_RETURN_NULL();
14917  }
14918 
14919  rt_raster_set_scale(raster, 0, 0);
14920  rt_raster_set_srid(raster, rt_raster_get_srid(_rast[0]));
14921  }
14922 
14923  for (k = 0; k < set_count; k++) {
14924  if (_rast[k] != NULL)
14925  rt_raster_destroy(_rast[k]);
14926  if (pgrastpos[k] != -1)
14927  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14928  }
14929 
14930  pgrtn = rt_raster_serialize(raster);
14931  rt_raster_destroy(raster);
14932  if (!pgrtn) PG_RETURN_NULL();
14933 
14934  SET_VARSIZE(pgrtn, pgrtn->size);
14935  PG_RETURN_POINTER(pgrtn);
14936  }
14937  break;
14938  case ET_LAST:
14939  case ET_CUSTOM:
14940  for (k = 0; k < set_count; k++) {
14941  if (_rast[k] != NULL)
14942  rt_raster_destroy(_rast[k]);
14943  if (pgrastpos[k] != -1)
14944  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14945  }
14946  elog(ERROR, "RASTER_mapAlgebra2: ET_LAST and ET_CUSTOM are not implemented");
14947  PG_RETURN_NULL();
14948  break;
14949  }
14950 
14951  /* both rasters do not have specified bands */
14952  if (
14953  (!_isempty[0] && !rt_raster_has_band(_rast[0], bandindex[0] - 1)) &&
14954  (!_isempty[1] && !rt_raster_has_band(_rast[1], bandindex[1] - 1))
14955  ) {
14956  elog(NOTICE, "The two rasters provided do not have the respectively specified band indices. Returning no band raster of correct extent");
14957 
14958  for (k = 0; k < set_count; k++) {
14959  if (_rast[k] != NULL)
14960  rt_raster_destroy(_rast[k]);
14961  if (pgrastpos[k] != -1)
14962  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14963  }
14964 
14965  pgrtn = rt_raster_serialize(raster);
14966  rt_raster_destroy(raster);
14967  if (!pgrtn) PG_RETURN_NULL();
14968 
14969  SET_VARSIZE(pgrtn, pgrtn->size);
14970  PG_RETURN_POINTER(pgrtn);
14971  }
14972 
14973  /* get bands */
14974  for (i = 0; i < set_count; i++) {
14975  if (_isempty[i] || !rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
14976  _hasnodata[i] = 1;
14977  _nodataval[i] = 0;
14978 
14979  continue;
14980  }
14981 
14982  _band[i] = rt_raster_get_band(_rast[i], bandindex[i] - 1);
14983  if (_band[i] == NULL) {
14984  for (k = 0; k < set_count; k++) {
14985  if (_rast[k] != NULL)
14986  rt_raster_destroy(_rast[k]);
14987  if (pgrastpos[k] != -1)
14988  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
14989  }
14990  rt_raster_destroy(raster);
14991  elog(ERROR, "RASTER_mapAlgebra2: Could not get band %d of the %s raster",
14992  bandindex[i],
14993  (i < 1 ? "FIRST" : "SECOND")
14994  );
14995  PG_RETURN_NULL();
14996  }
14997 
14998  _hasnodata[i] = rt_band_get_hasnodata_flag(_band[i]);
14999  if (_hasnodata[i])
15000  rt_band_get_nodata(_band[i], &(_nodataval[i]));
15001  }
15002 
15003  /* pixtype is PT_END, get pixtype based upon extent */
15004  if (pixtype == PT_END) {
15005  if ((extenttype == ET_SECOND && !_isempty[1]) || _isempty[0])
15006  pixtype = rt_band_get_pixtype(_band[1]);
15007  else
15008  pixtype = rt_band_get_pixtype(_band[0]);
15009  }
15010 
15011  /* nodata value for new band */
15012  if (extenttype == ET_SECOND && !_isempty[1] && _hasnodata[1]) {
15013  nodataval = _nodataval[1];
15014  }
15015  else if (!_isempty[0] && _hasnodata[0]) {
15016  nodataval = _nodataval[0];
15017  }
15018  else if (!_isempty[1] && _hasnodata[1]) {
15019  nodataval = _nodataval[1];
15020  }
15021  else {
15022  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));
15023  nodataval = rt_pixtype_get_min_value(pixtype);
15024  }
15025 
15026  /* add band to output raster */
15028  raster,
15029  pixtype,
15030  nodataval,
15031  1, nodataval,
15032  0
15033  ) < 0) {
15034  for (k = 0; k < set_count; k++) {
15035  if (_rast[k] != NULL)
15036  rt_raster_destroy(_rast[k]);
15037  if (pgrastpos[k] != -1)
15038  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15039  }
15040  rt_raster_destroy(raster);
15041  elog(ERROR, "RASTER_mapAlgebra2: Could not add new band to output raster");
15042  PG_RETURN_NULL();
15043  }
15044 
15045  /* get output band */
15046  band = rt_raster_get_band(raster, 0);
15047  if (band == NULL) {
15048  for (k = 0; k < set_count; k++) {
15049  if (_rast[k] != NULL)
15050  rt_raster_destroy(_rast[k]);
15051  if (pgrastpos[k] != -1)
15052  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15053  }
15054  rt_raster_destroy(raster);
15055  elog(ERROR, "RASTER_mapAlgebra2: Could not get newly added band of output raster");
15056  PG_RETURN_NULL();
15057  }
15058 
15059  POSTGIS_RT_DEBUGF(4, "offsets = (%d, %d, %d, %d)",
15060  (int) _rastoffset[0][0],
15061  (int) _rastoffset[0][1],
15062  (int) _rastoffset[1][0],
15063  (int) _rastoffset[1][1]
15064  );
15065 
15066  POSTGIS_RT_DEBUGF(4, "metadata = (%f, %f, %d, %d, %f, %f, %f, %f, %d)",
15067  rt_raster_get_x_offset(raster),
15068  rt_raster_get_y_offset(raster),
15069  rt_raster_get_width(raster),
15070  rt_raster_get_height(raster),
15071  rt_raster_get_x_scale(raster),
15072  rt_raster_get_y_scale(raster),
15073  rt_raster_get_x_skew(raster),
15074  rt_raster_get_y_skew(raster),
15075  rt_raster_get_srid(raster)
15076  );
15077 
15078  /*
15079  determine who called this function
15080  Arg 4 will either be text or regprocedure
15081  */
15082  POSTGIS_RT_DEBUG(3, "checking parameter type for arg 4");
15083  calltype = get_fn_expr_argtype(fcinfo->flinfo, 4);
15084 
15085  switch(calltype) {
15086  case TEXTOID: {
15087  POSTGIS_RT_DEBUG(3, "arg 4 is \"expression\"!");
15088 
15089  /* connect SPI */
15090  if (SPI_connect() != SPI_OK_CONNECT) {
15091  for (k = 0; k < set_count; k++) {
15092  if (_rast[k] != NULL)
15093  rt_raster_destroy(_rast[k]);
15094  if (pgrastpos[k] != -1)
15095  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15096  }
15097  rt_raster_destroy(raster);
15098  elog(ERROR, "RASTER_mapAlgebra2: Could not connect to the SPI manager");
15099  PG_RETURN_NULL();
15100  }
15101 
15102  /* reset hasargval */
15103  memset(hasargval, 0, sizeof(int) * spi_count);
15104 
15105  /*
15106  process expressions
15107 
15108  spi_exprpos elements are:
15109  4 - expression => spi_plan[0]
15110  7 - nodata1expr => spi_plan[1]
15111  8 - nodata2expr => spi_plan[2]
15112  */
15113  for (i = 0; i < spi_count; i++) {
15114  if (!PG_ARGISNULL(spi_exprpos[i])) {
15115  char *tmp = NULL;
15116  char place[5] = "$1";
15117  expr = text_to_cstring(PG_GETARG_TEXT_P(spi_exprpos[i]));
15118  POSTGIS_RT_DEBUGF(3, "raw expr #%d: %s", i, expr);
15119 
15120  for (j = 0, k = 1; j < argkwcount; j++) {
15121  /* attempt to replace keyword with placeholder */
15122  len = 0;
15123  tmp = rtpg_strreplace(expr, argkw[j], place, &len);
15124  pfree(expr);
15125  expr = tmp;
15126 
15127  if (len) {
15128  spi_argcount[i]++;
15129  argpos[i][j] = k++;
15130 
15131  sprintf(place, "$%d", k);
15132  }
15133  else
15134  argpos[i][j] = 0;
15135  }
15136 
15137  len = strlen("SELECT (") + strlen(expr) + strlen(")::double precision");
15138  sql = (char *) palloc(len + 1);
15139  if (sql == NULL) {
15140 
15141  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15142  SPI_finish();
15143 
15144  for (k = 0; k < set_count; k++) {
15145  if (_rast[k] != NULL)
15146  rt_raster_destroy(_rast[k]);
15147  if (pgrastpos[k] != -1)
15148  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15149  }
15150  rt_raster_destroy(raster);
15151 
15152  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for expression parameter %d", spi_exprpos[i]);
15153  PG_RETURN_NULL();
15154  }
15155 
15156  strncpy(sql, "SELECT (", strlen("SELECT ("));
15157  strncpy(sql + strlen("SELECT ("), expr, strlen(expr));
15158  strncpy(sql + strlen("SELECT (") + strlen(expr), ")::double precision", strlen(")::double precision"));
15159  sql[len] = '\0';
15160 
15161  POSTGIS_RT_DEBUGF(3, "sql #%d: %s", i, sql);
15162 
15163  /* create prepared plan */
15164  if (spi_argcount[i]) {
15165  argtype = (Oid *) palloc(spi_argcount[i] * sizeof(Oid));
15166  if (argtype == NULL) {
15167 
15168  pfree(sql);
15169  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15170  SPI_finish();
15171 
15172  for (k = 0; k < set_count; k++) {
15173  if (_rast[k] != NULL)
15174  rt_raster_destroy(_rast[k]);
15175  if (pgrastpos[k] != -1)
15176  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15177  }
15178  rt_raster_destroy(raster);
15179 
15180  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for prepared plan argtypes of expression parameter %d", spi_exprpos[i]);
15181  PG_RETURN_NULL();
15182  }
15183 
15184  /* specify datatypes of parameters */
15185  for (j = 0, k = 0; j < argkwcount; j++) {
15186  if (argpos[i][j] < 1) continue;
15187 
15188  /* positions are INT4 */
15189  if (
15190  (strstr(argkw[j], "[rast1.x]") != NULL) ||
15191  (strstr(argkw[j], "[rast1.y]") != NULL) ||
15192  (strstr(argkw[j], "[rast2.x]") != NULL) ||
15193  (strstr(argkw[j], "[rast2.y]") != NULL)
15194  ) {
15195  argtype[k] = INT4OID;
15196  }
15197  /* everything else is FLOAT8 */
15198  else {
15199  argtype[k] = FLOAT8OID;
15200  }
15201 
15202  k++;
15203  }
15204 
15205  spi_plan[i] = SPI_prepare(sql, spi_argcount[i], argtype);
15206  pfree(argtype);
15207 
15208  if (spi_plan[i] == NULL) {
15209 
15210  pfree(sql);
15211  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15212  SPI_finish();
15213 
15214  for (k = 0; k < set_count; k++) {
15215  if (_rast[k] != NULL)
15216  rt_raster_destroy(_rast[k]);
15217  if (pgrastpos[k] != -1)
15218  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15219  }
15220  rt_raster_destroy(raster);
15221 
15222  elog(ERROR, "RASTER_mapAlgebra2: Could not create prepared plan of expression parameter %d", spi_exprpos[i]);
15223  PG_RETURN_NULL();
15224  }
15225  }
15226  /* no args, just execute query */
15227  else {
15228  err = SPI_execute(sql, TRUE, 0);
15229  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
15230 
15231  pfree(sql);
15232  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15233  SPI_finish();
15234 
15235  for (k = 0; k < set_count; k++) {
15236  if (_rast[k] != NULL)
15237  rt_raster_destroy(_rast[k]);
15238  if (pgrastpos[k] != -1)
15239  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15240  }
15241  rt_raster_destroy(raster);
15242 
15243  elog(ERROR, "RASTER_mapAlgebra2: Could not evaluate expression parameter %d", spi_exprpos[i]);
15244  PG_RETURN_NULL();
15245  }
15246 
15247  /* get output of prepared plan */
15248  tupdesc = SPI_tuptable->tupdesc;
15249  tuptable = SPI_tuptable;
15250  tuple = tuptable->vals[0];
15251 
15252  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
15253  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
15254 
15255  pfree(sql);
15256  if (SPI_tuptable) SPI_freetuptable(tuptable);
15257  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15258  SPI_finish();
15259 
15260  for (k = 0; k < set_count; k++) {
15261  if (_rast[k] != NULL)
15262  rt_raster_destroy(_rast[k]);
15263  if (pgrastpos[k] != -1)
15264  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15265  }
15266  rt_raster_destroy(raster);
15267 
15268  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of expression parameter %d", spi_exprpos[i]);
15269  PG_RETURN_NULL();
15270  }
15271 
15272  if (!isnull) {
15273  hasargval[i] = 1;
15274  argval[i] = DatumGetFloat8(datum);
15275  }
15276 
15277  if (SPI_tuptable) SPI_freetuptable(tuptable);
15278  }
15279 
15280  pfree(sql);
15281  }
15282  else
15283  spi_empty++;
15284  }
15285 
15286  /* nodatanodataval */
15287  if (!PG_ARGISNULL(9)) {
15288  hasnodatanodataval = 1;
15289  nodatanodataval = PG_GETARG_FLOAT8(9);
15290  }
15291  else
15292  hasnodatanodataval = 0;
15293  break;
15294  }
15295  case REGPROCEDUREOID: {
15296  POSTGIS_RT_DEBUG(3, "arg 4 is \"userfunction\"!");
15297  if (!PG_ARGISNULL(4)) {
15298 
15299  ufc_nullcount = 0;
15300  ufc_noid = PG_GETARG_OID(4);
15301 
15302  /* get function info */
15303  fmgr_info(ufc_noid, &ufl_info);
15304 
15305  /* function cannot return set */
15306  err = 0;
15307  if (ufl_info.fn_retset) {
15308  err = 1;
15309  }
15310  /* function should have correct # of args */
15311  else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) {
15312  err = 2;
15313  }
15314 
15315  /*
15316  TODO: consider adding checks of the userfunction parameters
15317  should be able to use get_fn_expr_argtype() of fmgr.c
15318  */
15319 
15320  if (err > 0) {
15321  for (k = 0; k < set_count; k++) {
15322  if (_rast[k] != NULL)
15323  rt_raster_destroy(_rast[k]);
15324  if (pgrastpos[k] != -1)
15325  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15326  }
15327  rt_raster_destroy(raster);
15328 
15329  if (err > 1)
15330  elog(ERROR, "RASTER_mapAlgebra2: Function provided must have three or four input parameters");
15331  else
15332  elog(ERROR, "RASTER_mapAlgebra2: Function provided must return double precision not resultset");
15333  PG_RETURN_NULL();
15334  }
15335 
15336  if (func_volatile(ufc_noid) == 'v') {
15337  elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
15338  }
15339 
15340  /* prep function call data */
15341 #if POSTGIS_PGSQL_VERSION <= 90
15342  InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL);
15343 #else
15344  InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
15345 #endif
15346  memset(ufc_info.argnull, FALSE, sizeof(bool) * ufl_info.fn_nargs);
15347 
15348  if (ufl_info.fn_nargs != 4)
15349  k = 2;
15350  else
15351  k = 3;
15352  if (!PG_ARGISNULL(7)) {
15353  ufc_info.arg[k] = PG_GETARG_DATUM(7);
15354  }
15355  else {
15356  ufc_info.arg[k] = (Datum) NULL;
15357  ufc_info.argnull[k] = TRUE;
15358  ufc_nullcount++;
15359  }
15360  }
15361  break;
15362  }
15363  default:
15364  for (k = 0; k < set_count; k++) {
15365  if (_rast[k] != NULL)
15366  rt_raster_destroy(_rast[k]);
15367  if (pgrastpos[k] != -1)
15368  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15369  }
15370  rt_raster_destroy(raster);
15371  elog(ERROR, "RASTER_mapAlgebra2: Invalid data type for expression or userfunction");
15372  PG_RETURN_NULL();
15373  break;
15374  }
15375 
15376  /* loop over pixels */
15377  /* if any expression present, run */
15378  if ((
15379  (calltype == TEXTOID) && (
15380  (spi_empty != spi_count) || hasnodatanodataval
15381  )
15382  ) || (
15383  (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid)
15384  )) {
15385  for (x = 0; x < dim[0]; x++) {
15386  for (y = 0; y < dim[1]; y++) {
15387 
15388  /* get pixel from each raster */
15389  for (i = 0; i < set_count; i++) {
15390  _haspixel[i] = 0;
15391  _pixel[i] = 0;
15392 
15393  /* row/column */
15394  _x = x - (int) _rastoffset[i][0];
15395  _y = y - (int) _rastoffset[i][1];
15396 
15397  /* store _x and _y in 1-based */
15398  _pos[i][0] = _x + 1;
15399  _pos[i][1] = _y + 1;
15400 
15401  /* get pixel value */
15402  if (_band[i] == NULL) {
15403  if (!_hasnodata[i]) {
15404  _haspixel[i] = 1;
15405  _pixel[i] = _nodataval[i];
15406  }
15407  }
15408  else if (
15409  !_isempty[i] &&
15410  (_x >= 0 && _x < _dim[i][0]) &&
15411  (_y >= 0 && _y < _dim[i][1])
15412  ) {
15413  err = rt_band_get_pixel(_band[i], _x, _y, &(_pixel[i]), &isnodata);
15414  if (err != ES_NONE) {
15415 
15416  if (calltype == TEXTOID) {
15417  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15418  SPI_finish();
15419  }
15420 
15421  for (k = 0; k < set_count; k++) {
15422  if (_rast[k] != NULL)
15423  rt_raster_destroy(_rast[k]);
15424  if (pgrastpos[k] != -1)
15425  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15426  }
15427  rt_raster_destroy(raster);
15428 
15429  elog(ERROR, "RASTER_mapAlgebra2: Could not get pixel of %s raster", (i < 1 ? "FIRST" : "SECOND"));
15430  PG_RETURN_NULL();
15431  }
15432 
15433  if (!_hasnodata[i] || !isnodata)
15434  _haspixel[i] = 1;
15435  }
15436 
15437  POSTGIS_RT_DEBUGF(5, "pixel r%d(%d, %d) = %d, %f",
15438  i,
15439  _x, _y,
15440  _haspixel[i],
15441  _pixel[i]
15442  );
15443  }
15444 
15445  haspixel = 0;
15446 
15447  switch (calltype) {
15448  case TEXTOID: {
15449  /* which prepared plan to use? */
15450  /* !pixel0 && !pixel1 */
15451  /* use nodatanodataval */
15452  if (!_haspixel[0] && !_haspixel[1])
15453  i = 3;
15454  /* pixel0 && !pixel1 */
15455  /* run spi_plan[2] (nodata2expr) */
15456  else if (_haspixel[0] && !_haspixel[1])
15457  i = 2;
15458  /* !pixel0 && pixel1 */
15459  /* run spi_plan[1] (nodata1expr) */
15460  else if (!_haspixel[0] && _haspixel[1])
15461  i = 1;
15462  /* pixel0 && pixel1 */
15463  /* run spi_plan[0] (expression) */
15464  else
15465  i = 0;
15466 
15467  /* process values */
15468  if (i == 3) {
15469  if (hasnodatanodataval) {
15470  haspixel = 1;
15471  pixel = nodatanodataval;
15472  }
15473  }
15474  /* has an evaluated value */
15475  else if (hasargval[i]) {
15476  haspixel = 1;
15477  pixel = argval[i];
15478  }
15479  /* prepared plan exists */
15480  else if (spi_plan[i] != NULL) {
15481  POSTGIS_RT_DEBUGF(4, "Using prepared plan: %d", i);
15482 
15483  /* expression has argument(s) */
15484  if (spi_argcount[i]) {
15485  /* reset values to (Datum) NULL */
15486  memset(values, (Datum) NULL, sizeof(Datum) * argkwcount);
15487  /* reset nulls to FALSE */
15488  memset(nulls, FALSE, sizeof(bool) * argkwcount);
15489 
15490  /* set values and nulls */
15491  for (j = 0; j < argkwcount; j++) {
15492  idx = argpos[i][j];
15493  if (idx < 1) continue;
15494  idx--; /* 1-based becomes 0-based */
15495 
15496  if (strstr(argkw[j], "[rast1.x]") != NULL) {
15497  values[idx] = _pos[0][0];
15498  }
15499  else if (strstr(argkw[j], "[rast1.y]") != NULL) {
15500  values[idx] = _pos[0][1];
15501  }
15502  else if (
15503  (strstr(argkw[j], "[rast1.val]") != NULL) ||
15504  (strstr(argkw[j], "[rast1]") != NULL)
15505  ) {
15506  if (_isempty[0] || !_haspixel[0])
15507  nulls[idx] = TRUE;
15508  else
15509  values[idx] = Float8GetDatum(_pixel[0]);
15510  }
15511  else if (strstr(argkw[j], "[rast2.x]") != NULL) {
15512  values[idx] = _pos[1][0];
15513  }
15514  else if (strstr(argkw[j], "[rast2.y]") != NULL) {
15515  values[idx] = _pos[1][1];
15516  }
15517  else if (
15518  (strstr(argkw[j], "[rast2.val]") != NULL) ||
15519  (strstr(argkw[j], "[rast2]") != NULL)
15520  ) {
15521  if (_isempty[1] || !_haspixel[1])
15522  nulls[idx] = TRUE;
15523  else
15524  values[idx] = Float8GetDatum(_pixel[1]);
15525  }
15526  }
15527  }
15528 
15529  /* run prepared plan */
15530  err = SPI_execute_plan(spi_plan[i], values, nulls, TRUE, 1);
15531  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
15532 
15533  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15534  SPI_finish();
15535 
15536  for (k = 0; k < set_count; k++) {
15537  if (_rast[k] != NULL)
15538  rt_raster_destroy(_rast[k]);
15539  if (pgrastpos[k] != -1)
15540  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15541  }
15542  rt_raster_destroy(raster);
15543 
15544  elog(ERROR, "RASTER_mapAlgebra2: Unexpected error when running prepared statement %d", i);
15545  PG_RETURN_NULL();
15546  }
15547 
15548  /* get output of prepared plan */
15549  tupdesc = SPI_tuptable->tupdesc;
15550  tuptable = SPI_tuptable;
15551  tuple = tuptable->vals[0];
15552 
15553  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
15554  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
15555 
15556  if (SPI_tuptable) SPI_freetuptable(tuptable);
15557  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15558  SPI_finish();
15559 
15560  for (k = 0; k < set_count; k++) {
15561  if (_rast[k] != NULL)
15562  rt_raster_destroy(_rast[k]);
15563  if (pgrastpos[k] != -1)
15564  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15565  }
15566  rt_raster_destroy(raster);
15567 
15568  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of prepared statement %d", i);
15569  PG_RETURN_NULL();
15570  }
15571 
15572  if (!isnull) {
15573  haspixel = 1;
15574  pixel = DatumGetFloat8(datum);
15575  }
15576 
15577  if (SPI_tuptable) SPI_freetuptable(tuptable);
15578  }
15579  } break;
15580  case REGPROCEDUREOID: {
15581  Datum d[4];
15582  ArrayType *a;
15583 
15584  /* build fcnarg */
15585  for (i = 0; i < set_count; i++) {
15586  ufc_info.arg[i] = Float8GetDatum(_pixel[i]);
15587 
15588  if (_haspixel[i]) {
15589  ufc_info.argnull[i] = FALSE;
15590  ufc_nullcount--;
15591  }
15592  else {
15593  ufc_info.argnull[i] = TRUE;
15594  ufc_nullcount++;
15595  }
15596  }
15597 
15598  /* function is strict and null parameter is passed */
15599  /* http://archives.postgresql.org/pgsql-general/2011-11/msg00424.php */
15600  if (ufl_info.fn_strict && ufc_nullcount)
15601  break;
15602 
15603  /* 4 parameters, add position */
15604  if (ufl_info.fn_nargs == 4) {
15605  /* Datum of 4 element array */
15606  /* array is (x1, y1, x2, y2) */
15607  for (i = 0; i < set_count; i++) {
15608  if (i < 1) {
15609  d[0] = Int32GetDatum(_pos[i][0]);
15610  d[1] = Int32GetDatum(_pos[i][1]);
15611  }
15612  else {
15613  d[2] = Int32GetDatum(_pos[i][0]);
15614  d[3] = Int32GetDatum(_pos[i][1]);
15615  }
15616  }
15617 
15618  a = construct_array(d, 4, INT4OID, sizeof(int32), true, 'i');
15619  ufc_info.arg[2] = PointerGetDatum(a);
15620  ufc_info.argnull[2] = FALSE;
15621  }
15622 
15623  datum = FunctionCallInvoke(&ufc_info);
15624 
15625  /* result is not null*/
15626  if (!ufc_info.isnull) {
15627  haspixel = 1;
15628  pixel = DatumGetFloat8(datum);
15629  }
15630  } break;
15631  }
15632 
15633  /* burn pixel if haspixel != 0 */
15634  if (haspixel) {
15635  if (rt_band_set_pixel(band, x, y, pixel, NULL) != ES_NONE) {
15636 
15637  if (calltype == TEXTOID) {
15638  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
15639  SPI_finish();
15640  }
15641 
15642  for (k = 0; k < set_count; k++) {
15643  if (_rast[k] != NULL)
15644  rt_raster_destroy(_rast[k]);
15645  if (pgrastpos[k] != -1)
15646  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15647  }
15648  rt_raster_destroy(raster);
15649 
15650  elog(ERROR, "RASTER_mapAlgebra2: Could not set pixel value of output raster");
15651  PG_RETURN_NULL();
15652  }
15653  }
15654 
15655  POSTGIS_RT_DEBUGF(5, "(x, y, val) = (%d, %d, %f)", x, y, haspixel ? pixel : nodataval);
15656 
15657  } /* y: height */
15658  } /* x: width */
15659  }
15660 
15661  /* CLEANUP */
15662  if (calltype == TEXTOID) {
15663  for (i = 0; i < spi_count; i++) {
15664  if (spi_plan[i] != NULL) SPI_freeplan(spi_plan[i]);
15665  }
15666  SPI_finish();
15667  }
15668 
15669  for (k = 0; k < set_count; k++) {
15670  if (_rast[k] != NULL)
15671  rt_raster_destroy(_rast[k]);
15672  if (pgrastpos[k] != -1)
15673  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
15674  }
15675 
15676  pgrtn = rt_raster_serialize(raster);
15677  rt_raster_destroy(raster);
15678  if (!pgrtn) PG_RETURN_NULL();
15679 
15680  POSTGIS_RT_DEBUG(3, "Finished RASTER_mapAlgebra2");
15681 
15682  SET_VARSIZE(pgrtn, pgrtn->size);
15683  PG_RETURN_POINTER(pgrtn);
15684 }
static char * rtpg_strtoupper(char *str)
Definition: rt_pg.c:730
static char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
Definition: rt_pg.c:685
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_api.c:8158
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
Definition: rt_api.c:5527
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_api.c:5387
static char * rtpg_trim(const char *input)
Definition: rt_pg.c:856
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_api.c:1168
tuple gt
Definition: window.py:79
Definition: rt_api.h:184
rt_extenttype rt_util_extent_type(const char *name)
Definition: rt_api.c:302
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_api.c:1900
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition: rt_api.c:5486
tuple band
Definition: ovdump.py:57
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
Definition: rt_api.c:8563
tuple rast
Definition: rtpixdump.py:62
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition: rt_api.c:5495
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition: rt_api.c:5518
tuple raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:123
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_api.c:1206
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
Definition: rt_api.c:12876
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition: rt_api.c:5668
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition: rt_api.c:5661
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_api.c:6005
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
Definition: rt_api.c:5442
rt_pixtype
Definition: rt_api.h:172
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rt_pg.h:58
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_api.c:3058
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_api.c:2549
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
Definition: rt_api.c:6026
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition: rt_api.c:5455
tuple x
Definition: pixval.py:53
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_api.c:5434
rt_extenttype
Definition: rt_api.h:187
rt_band rt_raster_get_band(rt_raster raster, int n)
Return Nth band, or NULL if unavailable.
Definition: rt_api.c:5686
#define FALSE
Definition: dbfopen.c:169
Struct definitions.
Definition: rt_api.h:2175
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rt_pg.h:62
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_api.c:8550
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition: rt_api.c:5464
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_api.c:8350
tuple pixel
Definition: pixval.py:90
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition: rt_api.c:1138
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_api.c:5353
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
Definition: rt_api.c:12774
#define TRUE
Definition: dbfopen.c:170
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_api.c:2002
tuple y
Definition: pixval.py:54
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_api.c:5426
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_api.c:5784
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
Definition: rt_api.c:2302

Here is the call graph for this function: