PostGIS  2.5.0dev-r@@SVN_REVISION@@
Datum RASTER_union_transfn ( PG_FUNCTION_ARGS  )

Definition at line 2057 of file rtpg_mapalgebra.c.

References rtpg_union_arg_t::bandarg, ES_NONE, ET_LAST, ET_UNION, FALSE, window::gt, pixval::nband, rtpg_union_band_arg_t::nband, rt_iterator_t::nband, rt_iterator_t::nbnodata, rtpg_union_arg_t::numband, rtpg_union_band_arg_t::numraster, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, PT_32BUI, PT_64BF, PT_END, rtrowdump::raster, rtpg_union_band_arg_t::raster, rt_iterator_t::raster, rt_band_destroy(), rt_band_get_hasnodata_flag(), rt_band_get_min_value(), rt_band_get_nodata(), rt_band_get_pixel_line(), rt_band_get_pixtype(), rt_band_set_pixel_line(), rt_pixtype_get_min_value(), rt_pixtype_name(), rt_raster_clone(), 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_num_bands(), rt_raster_get_width(), rt_raster_has_band(), rt_raster_is_empty(), rt_raster_iterator(), rt_util_same_geotransform_matrix(), rtpg_strtoupper(), rtpg_union_arg_destroy(), rtpg_union_callback(), rtpg_union_noarg(), rtpg_union_unionarg_process(), rtpg_uniontype_index_from_name(), rtpg_union_band_arg_t::uniontype, UT_COUNT, UT_LAST, UT_MAX, UT_MEAN, UT_MIN, UT_RANGE, UT_SUM, and pixval::y.

2058 {
2059  MemoryContext aggcontext;
2060  MemoryContext oldcontext;
2061  rtpg_union_arg iwr = NULL;
2062  int skiparg = 0;
2063 
2064  rt_pgraster *pgraster = NULL;
2065  rt_raster raster = NULL;
2066  rt_raster _raster = NULL;
2067  rt_band _band = NULL;
2068  int nband = 1;
2069  int noerr = 1;
2070  int isempty[2] = {0};
2071  int hasband[2] = {0};
2072  int nargs = 0;
2073  double _offset[4] = {0.};
2074  int nbnodata = 0; /* 1 if adding bands */
2075 
2076  int i = 0;
2077  int j = 0;
2078  int k = 0;
2079 
2080  rt_iterator itrset;
2081  char *utypename = NULL;
2082  rtpg_union_type utype = UT_LAST;
2083  rt_pixtype pixtype = PT_END;
2084  int hasnodata = 1;
2085  double nodataval = 0;
2086 
2087  rt_raster iraster = NULL;
2088  rt_band iband = NULL;
2089  int reuserast = 0;
2090  int y = 0;
2091  uint16_t _dim[2] = {0};
2092  void *vals = NULL;
2093  uint16_t nvals = 0;
2094 
2095  POSTGIS_RT_DEBUG(3, "Starting...");
2096 
2097  /* cannot be called directly as this is exclusive aggregate function */
2098  if (!AggCheckCallContext(fcinfo, &aggcontext)) {
2099  elog(ERROR, "RASTER_union_transfn: Cannot be called in a non-aggregate context");
2100  PG_RETURN_NULL();
2101  }
2102 
2103  /* switch to aggcontext */
2104  oldcontext = MemoryContextSwitchTo(aggcontext);
2105 
2106  if (PG_ARGISNULL(0)) {
2107  POSTGIS_RT_DEBUG(3, "Creating state variable");
2108  /* allocate container in aggcontext */
2109  iwr = palloc(sizeof(struct rtpg_union_arg_t));
2110  if (iwr == NULL) {
2111  MemoryContextSwitchTo(oldcontext);
2112  elog(ERROR, "RASTER_union_transfn: Could not allocate memory for state variable");
2113  PG_RETURN_NULL();
2114  }
2115 
2116  iwr->numband = 0;
2117  iwr->bandarg = NULL;
2118 
2119  skiparg = 0;
2120  }
2121  else {
2122  POSTGIS_RT_DEBUG(3, "State variable already exists");
2123  iwr = (rtpg_union_arg) PG_GETARG_POINTER(0);
2124  skiparg = 1;
2125  }
2126 
2127  /* raster arg is NOT NULL */
2128  if (!PG_ARGISNULL(1)) {
2129  /* deserialize raster */
2130  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
2131 
2132  /* Get raster object */
2133  raster = rt_raster_deserialize(pgraster, FALSE);
2134  if (raster == NULL) {
2135 
2137  PG_FREE_IF_COPY(pgraster, 1);
2138 
2139  MemoryContextSwitchTo(oldcontext);
2140  elog(ERROR, "RASTER_union_transfn: Could not deserialize raster");
2141  PG_RETURN_NULL();
2142  }
2143  }
2144 
2145  /* process additional args if needed */
2146  nargs = PG_NARGS();
2147  POSTGIS_RT_DEBUGF(4, "nargs = %d", nargs);
2148  if (nargs > 2) {
2149  POSTGIS_RT_DEBUG(4, "processing additional arguments");
2150 
2151  /* if more than 2 arguments, determine the type of argument 3 */
2152  /* band number, UNION type or unionarg */
2153  if (!PG_ARGISNULL(2)) {
2154  Oid calltype = get_fn_expr_argtype(fcinfo->flinfo, 2);
2155 
2156  switch (calltype) {
2157  /* UNION type */
2158  case TEXTOID: {
2159  int idx = 0;
2160  int numband = 0;
2161 
2162  POSTGIS_RT_DEBUG(4, "Processing arg 3 as UNION type");
2163  nbnodata = 1;
2164 
2165  utypename = text_to_cstring(PG_GETARG_TEXT_P(2));
2166  utype = rtpg_uniontype_index_from_name(rtpg_strtoupper(utypename));
2167  POSTGIS_RT_DEBUGF(4, "Union type: %s", utypename);
2168 
2169  POSTGIS_RT_DEBUGF(4, "iwr->numband: %d", iwr->numband);
2170  /* see if we need to append new bands */
2171  if (raster) {
2172  idx = iwr->numband;
2173  numband = rt_raster_get_num_bands(raster);
2174  POSTGIS_RT_DEBUGF(4, "numband: %d", numband);
2175 
2176  /* only worry about appended bands */
2177  if (numband > iwr->numband)
2178  iwr->numband = numband;
2179  }
2180 
2181  if (!iwr->numband)
2182  iwr->numband = 1;
2183  POSTGIS_RT_DEBUGF(4, "iwr->numband: %d", iwr->numband);
2184  POSTGIS_RT_DEBUGF(4, "numband, idx: %d, %d", numband, idx);
2185 
2186  /* bandarg set. only possible after the first call to function */
2187  if (iwr->bandarg) {
2188  /* only reallocate if new bands need to be added */
2189  if (numband > idx) {
2190  POSTGIS_RT_DEBUG(4, "Reallocating iwr->bandarg");
2191  iwr->bandarg = repalloc(iwr->bandarg, sizeof(struct rtpg_union_band_arg_t) * iwr->numband);
2192  }
2193  /* prevent initial values step happening below */
2194  else
2195  idx = iwr->numband;
2196  }
2197  /* bandarg not set, first call to function */
2198  else {
2199  POSTGIS_RT_DEBUG(4, "Allocating iwr->bandarg");
2200  iwr->bandarg = palloc(sizeof(struct rtpg_union_band_arg_t) * iwr->numband);
2201  }
2202  if (iwr->bandarg == NULL) {
2203 
2205  if (raster != NULL) {
2206  rt_raster_destroy(raster);
2207  PG_FREE_IF_COPY(pgraster, 1);
2208  }
2209 
2210  MemoryContextSwitchTo(oldcontext);
2211  elog(ERROR, "RASTER_union_transfn: Could not allocate memory for band information");
2212  PG_RETURN_NULL();
2213  }
2214 
2215  /* set initial values for bands that are "new" */
2216  for (i = idx; i < iwr->numband; i++) {
2217  iwr->bandarg[i].uniontype = utype;
2218  iwr->bandarg[i].nband = i;
2219 
2220  if (
2221  utype == UT_MEAN ||
2222  utype == UT_RANGE
2223  ) {
2224  iwr->bandarg[i].numraster = 2;
2225  }
2226  else
2227  iwr->bandarg[i].numraster = 1;
2228  iwr->bandarg[i].raster = NULL;
2229  }
2230 
2231  break;
2232  }
2233  /* band number */
2234  case INT2OID:
2235  case INT4OID:
2236  if (skiparg)
2237  break;
2238 
2239  POSTGIS_RT_DEBUG(4, "Processing arg 3 as band number");
2240  nband = PG_GETARG_INT32(2);
2241  if (nband < 1) {
2242 
2244  if (raster != NULL) {
2245  rt_raster_destroy(raster);
2246  PG_FREE_IF_COPY(pgraster, 1);
2247  }
2248 
2249  MemoryContextSwitchTo(oldcontext);
2250  elog(ERROR, "RASTER_union_transfn: Band number must be greater than zero (1-based)");
2251  PG_RETURN_NULL();
2252  }
2253 
2254  iwr->numband = 1;
2255  iwr->bandarg = palloc(sizeof(struct rtpg_union_band_arg_t) * iwr->numband);
2256  if (iwr->bandarg == NULL) {
2257 
2259  if (raster != NULL) {
2260  rt_raster_destroy(raster);
2261  PG_FREE_IF_COPY(pgraster, 1);
2262  }
2263 
2264  MemoryContextSwitchTo(oldcontext);
2265  elog(ERROR, "RASTER_union_transfn: Could not allocate memory for band information");
2266  PG_RETURN_NULL();
2267  }
2268 
2269  iwr->bandarg[0].uniontype = UT_LAST;
2270  iwr->bandarg[0].nband = nband - 1;
2271 
2272  iwr->bandarg[0].numraster = 1;
2273  iwr->bandarg[0].raster = NULL;
2274  break;
2275  /* only other type allowed is unionarg */
2276  default:
2277  if (skiparg)
2278  break;
2279 
2280  POSTGIS_RT_DEBUG(4, "Processing arg 3 as unionarg");
2281  if (!rtpg_union_unionarg_process(iwr, PG_GETARG_ARRAYTYPE_P(2))) {
2282 
2284  if (raster != NULL) {
2285  rt_raster_destroy(raster);
2286  PG_FREE_IF_COPY(pgraster, 1);
2287  }
2288 
2289  MemoryContextSwitchTo(oldcontext);
2290  elog(ERROR, "RASTER_union_transfn: Could not process unionarg");
2291  PG_RETURN_NULL();
2292  }
2293 
2294  break;
2295  }
2296  }
2297 
2298  /* UNION type */
2299  if (nargs > 3 && !PG_ARGISNULL(3)) {
2300  utypename = text_to_cstring(PG_GETARG_TEXT_P(3));
2301  utype = rtpg_uniontype_index_from_name(rtpg_strtoupper(utypename));
2302  iwr->bandarg[0].uniontype = utype;
2303  POSTGIS_RT_DEBUGF(4, "Union type: %s", utypename);
2304 
2305  if (
2306  utype == UT_MEAN ||
2307  utype == UT_RANGE
2308  ) {
2309  iwr->bandarg[0].numraster = 2;
2310  }
2311  }
2312 
2313  /* allocate space for pointers to rt_raster */
2314  for (i = 0; i < iwr->numband; i++) {
2315  POSTGIS_RT_DEBUGF(4, "iwr->bandarg[%d].raster @ %p", i, iwr->bandarg[i].raster);
2316 
2317  /* no need to allocate */
2318  if (iwr->bandarg[i].raster != NULL)
2319  continue;
2320 
2321  POSTGIS_RT_DEBUGF(4, "Allocating space for working rasters of band %d", i);
2322 
2323  iwr->bandarg[i].raster = (rt_raster *) palloc(sizeof(rt_raster) * iwr->bandarg[i].numraster);
2324  if (iwr->bandarg[i].raster == NULL) {
2325 
2327  if (raster != NULL) {
2328  rt_raster_destroy(raster);
2329  PG_FREE_IF_COPY(pgraster, 1);
2330  }
2331 
2332  MemoryContextSwitchTo(oldcontext);
2333  elog(ERROR, "RASTER_union_transfn: Could not allocate memory for working raster(s)");
2334  PG_RETURN_NULL();
2335  }
2336 
2337  memset(iwr->bandarg[i].raster, 0, sizeof(rt_raster) * iwr->bandarg[i].numraster);
2338 
2339  /* add new working rt_raster but only if working raster already exists */
2340  if (i > 0 && !rt_raster_is_empty(iwr->bandarg[0].raster[0])) {
2341  for (j = 0; j < iwr->bandarg[i].numraster; j++) {
2342  iwr->bandarg[i].raster[j] = rt_raster_clone(iwr->bandarg[0].raster[0], 0); /* shallow clone */
2343  if (iwr->bandarg[i].raster[j] == NULL) {
2344 
2346  if (raster != NULL) {
2347  rt_raster_destroy(raster);
2348  PG_FREE_IF_COPY(pgraster, 1);
2349  }
2350 
2351  MemoryContextSwitchTo(oldcontext);
2352  elog(ERROR, "RASTER_union_transfn: Could not create working raster");
2353  PG_RETURN_NULL();
2354  }
2355  }
2356  }
2357  }
2358  }
2359  /* only raster, no additional args */
2360  /* only do this if raster isn't empty */
2361  else {
2362  POSTGIS_RT_DEBUG(4, "no additional args, checking input raster");
2363  nbnodata = 1;
2364  if (!rtpg_union_noarg(iwr, raster)) {
2365 
2367  if (raster != NULL) {
2368  rt_raster_destroy(raster);
2369  PG_FREE_IF_COPY(pgraster, 1);
2370  }
2371 
2372  MemoryContextSwitchTo(oldcontext);
2373  elog(ERROR, "RASTER_union_transfn: Could not check and balance number of bands");
2374  PG_RETURN_NULL();
2375  }
2376  }
2377 
2378  /* init itrset */
2379  itrset = palloc(sizeof(struct rt_iterator_t) * 2);
2380  if (itrset == NULL) {
2381 
2383  if (raster != NULL) {
2384  rt_raster_destroy(raster);
2385  PG_FREE_IF_COPY(pgraster, 1);
2386  }
2387 
2388  MemoryContextSwitchTo(oldcontext);
2389  elog(ERROR, "RASTER_union_transfn: Could not allocate memory for iterator arguments");
2390  PG_RETURN_NULL();
2391  }
2392 
2393  /* by band to UNION */
2394  for (i = 0; i < iwr->numband; i++) {
2395 
2396  /* by raster */
2397  for (j = 0; j < iwr->bandarg[i].numraster; j++) {
2398  reuserast = 0;
2399 
2400  /* type of union */
2401  utype = iwr->bandarg[i].uniontype;
2402 
2403  /* raster flags */
2404  isempty[0] = rt_raster_is_empty(iwr->bandarg[i].raster[j]);
2405  isempty[1] = rt_raster_is_empty(raster);
2406 
2407  if (!isempty[0])
2408  hasband[0] = rt_raster_has_band(iwr->bandarg[i].raster[j], 0);
2409  if (!isempty[1])
2410  hasband[1] = rt_raster_has_band(raster, iwr->bandarg[i].nband);
2411 
2412  /* determine pixtype, hasnodata and nodataval */
2413  _band = NULL;
2414  if (!isempty[0] && hasband[0])
2415  _band = rt_raster_get_band(iwr->bandarg[i].raster[j], 0);
2416  else if (!isempty[1] && hasband[1])
2417  _band = rt_raster_get_band(raster, iwr->bandarg[i].nband);
2418  else {
2419  pixtype = PT_64BF;
2420  hasnodata = 1;
2421  nodataval = rt_pixtype_get_min_value(pixtype);
2422  }
2423  if (_band != NULL) {
2424  pixtype = rt_band_get_pixtype(_band);
2425  hasnodata = 1;
2426  if (rt_band_get_hasnodata_flag(_band))
2427  rt_band_get_nodata(_band, &nodataval);
2428  else
2429  nodataval = rt_band_get_min_value(_band);
2430  }
2431 
2432  /* UT_MEAN and UT_RANGE require two passes */
2433  /* UT_MEAN: first for UT_COUNT and second for UT_SUM */
2434  if (iwr->bandarg[i].uniontype == UT_MEAN) {
2435  /* first pass, UT_COUNT */
2436  if (j < 1)
2437  utype = UT_COUNT;
2438  else
2439  utype = UT_SUM;
2440  }
2441  /* UT_RANGE: first for UT_MIN and second for UT_MAX */
2442  else if (iwr->bandarg[i].uniontype == UT_RANGE) {
2443  /* first pass, UT_MIN */
2444  if (j < 1)
2445  utype = UT_MIN;
2446  else
2447  utype = UT_MAX;
2448  }
2449 
2450  /* force band settings for UT_COUNT */
2451  if (utype == UT_COUNT) {
2452  pixtype = PT_32BUI;
2453  hasnodata = 0;
2454  nodataval = 0;
2455  }
2456 
2457  POSTGIS_RT_DEBUGF(4, "(pixtype, hasnodata, nodataval) = (%s, %d, %f)", rt_pixtype_name(pixtype), hasnodata, nodataval);
2458 
2459  /* set itrset */
2460  itrset[0].raster = iwr->bandarg[i].raster[j];
2461  itrset[0].nband = 0;
2462  itrset[1].raster = raster;
2463  itrset[1].nband = iwr->bandarg[i].nband;
2464 
2465  /* allow use NODATA to replace missing bands */
2466  if (nbnodata) {
2467  itrset[0].nbnodata = 1;
2468  itrset[1].nbnodata = 1;
2469  }
2470  /* missing bands are not ignored */
2471  else {
2472  itrset[0].nbnodata = 0;
2473  itrset[1].nbnodata = 0;
2474  }
2475 
2476  /* if rasters AND bands are present, use copy approach */
2477  if (!isempty[0] && !isempty[1] && hasband[0] && hasband[1]) {
2478  POSTGIS_RT_DEBUG(3, "using line method");
2479 
2480  /* generate empty out raster */
2482  iwr->bandarg[i].raster[j], raster,
2483  ET_UNION,
2484  &iraster, _offset
2485  ) != ES_NONE) {
2486 
2487  pfree(itrset);
2489  if (raster != NULL) {
2490  rt_raster_destroy(raster);
2491  PG_FREE_IF_COPY(pgraster, 1);
2492  }
2493 
2494  MemoryContextSwitchTo(oldcontext);
2495  elog(ERROR, "RASTER_union_transfn: Could not create internal raster");
2496  PG_RETURN_NULL();
2497  }
2498  POSTGIS_RT_DEBUGF(4, "_offset = %f, %f, %f, %f",
2499  _offset[0], _offset[1], _offset[2], _offset[3]);
2500 
2501  /* rasters are spatially the same? */
2502  if (
2503  rt_raster_get_width(iwr->bandarg[i].raster[j]) == rt_raster_get_width(iraster) &&
2505  ) {
2506  double igt[6] = {0};
2507  double gt[6] = {0};
2508 
2510  rt_raster_get_geotransform_matrix(iraster, igt);
2511 
2512  reuserast = rt_util_same_geotransform_matrix(gt, igt);
2513  }
2514 
2515  /* use internal raster */
2516  if (!reuserast) {
2517  /* create band of same type */
2519  iraster,
2520  pixtype,
2521  nodataval,
2522  hasnodata, nodataval,
2523  0
2524  ) == -1) {
2525 
2526  pfree(itrset);
2528  rt_raster_destroy(iraster);
2529  if (raster != NULL) {
2530  rt_raster_destroy(raster);
2531  PG_FREE_IF_COPY(pgraster, 1);
2532  }
2533 
2534  MemoryContextSwitchTo(oldcontext);
2535  elog(ERROR, "RASTER_union_transfn: Could not add new band to internal raster");
2536  PG_RETURN_NULL();
2537  }
2538  iband = rt_raster_get_band(iraster, 0);
2539 
2540  /* copy working raster to output raster */
2541  _dim[0] = rt_raster_get_width(iwr->bandarg[i].raster[j]);
2542  _dim[1] = rt_raster_get_height(iwr->bandarg[i].raster[j]);
2543  for (y = 0; y < _dim[1]; y++) {
2544  POSTGIS_RT_DEBUGF(4, "Getting pixel line of working raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2546  _band,
2547  0, y,
2548  _dim[0],
2549  &vals, &nvals
2550  ) != ES_NONE) {
2551 
2552  pfree(itrset);
2554  rt_band_destroy(iband);
2555  rt_raster_destroy(iraster);
2556  if (raster != NULL) {
2557  rt_raster_destroy(raster);
2558  PG_FREE_IF_COPY(pgraster, 1);
2559  }
2560 
2561  MemoryContextSwitchTo(oldcontext);
2562  elog(ERROR, "RASTER_union_transfn: Could not get pixel line from band of working raster");
2563  PG_RETURN_NULL();
2564  }
2565 
2566  POSTGIS_RT_DEBUGF(4, "Setting pixel line at (x, y, length) = (%d, %d, %d)", (int) _offset[0], (int) _offset[1] + y, nvals);
2568  iband,
2569  (int) _offset[0], (int) _offset[1] + y,
2570  vals, nvals
2571  ) != ES_NONE) {
2572 
2573  pfree(itrset);
2575  rt_band_destroy(iband);
2576  rt_raster_destroy(iraster);
2577  if (raster != NULL) {
2578  rt_raster_destroy(raster);
2579  PG_FREE_IF_COPY(pgraster, 1);
2580  }
2581 
2582  MemoryContextSwitchTo(oldcontext);
2583  elog(ERROR, "RASTER_union_transfn: Could not set pixel line to band of internal raster");
2584  PG_RETURN_NULL();
2585  }
2586  }
2587  }
2588  else {
2589  rt_raster_destroy(iraster);
2590  iraster = iwr->bandarg[i].raster[j];
2591  iband = rt_raster_get_band(iraster, 0);
2592  }
2593 
2594  /* run iterator for extent of input raster */
2595  noerr = rt_raster_iterator(
2596  itrset, 2,
2597  ET_LAST, NULL,
2598  pixtype,
2599  hasnodata, nodataval,
2600  0, 0,
2601  NULL,
2602  &utype,
2604  &_raster
2605  );
2606  if (noerr != ES_NONE) {
2607 
2608  pfree(itrset);
2610  if (!reuserast) {
2611  rt_band_destroy(iband);
2612  rt_raster_destroy(iraster);
2613  }
2614  if (raster != NULL) {
2615  rt_raster_destroy(raster);
2616  PG_FREE_IF_COPY(pgraster, 1);
2617  }
2618 
2619  MemoryContextSwitchTo(oldcontext);
2620  elog(ERROR, "RASTER_union_transfn: Could not run raster iterator function");
2621  PG_RETURN_NULL();
2622  }
2623 
2624  /* with iterator raster, copy data to output raster */
2625  _band = rt_raster_get_band(_raster, 0);
2626  _dim[0] = rt_raster_get_width(_raster);
2627  _dim[1] = rt_raster_get_height(_raster);
2628  for (y = 0; y < _dim[1]; y++) {
2629  POSTGIS_RT_DEBUGF(4, "Getting pixel line of iterator raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2631  _band,
2632  0, y,
2633  _dim[0],
2634  &vals, &nvals
2635  ) != ES_NONE) {
2636 
2637  pfree(itrset);
2639  if (!reuserast) {
2640  rt_band_destroy(iband);
2641  rt_raster_destroy(iraster);
2642  }
2643  if (raster != NULL) {
2644  rt_raster_destroy(raster);
2645  PG_FREE_IF_COPY(pgraster, 1);
2646  }
2647 
2648  MemoryContextSwitchTo(oldcontext);
2649  elog(ERROR, "RASTER_union_transfn: Could not get pixel line from band of working raster");
2650  PG_RETURN_NULL();
2651  }
2652 
2653  POSTGIS_RT_DEBUGF(4, "Setting pixel line at (x, y, length) = (%d, %d, %d)", (int) _offset[2], (int) _offset[3] + y, nvals);
2655  iband,
2656  (int) _offset[2], (int) _offset[3] + y,
2657  vals, nvals
2658  ) != ES_NONE) {
2659 
2660  pfree(itrset);
2662  if (!reuserast) {
2663  rt_band_destroy(iband);
2664  rt_raster_destroy(iraster);
2665  }
2666  if (raster != NULL) {
2667  rt_raster_destroy(raster);
2668  PG_FREE_IF_COPY(pgraster, 1);
2669  }
2670 
2671  MemoryContextSwitchTo(oldcontext);
2672  elog(ERROR, "RASTER_union_transfn: Could not set pixel line to band of internal raster");
2673  PG_RETURN_NULL();
2674  }
2675  }
2676 
2677  /* free _raster */
2678  rt_band_destroy(_band);
2679  rt_raster_destroy(_raster);
2680 
2681  /* replace working raster with output raster */
2682  _raster = iraster;
2683  }
2684  else {
2685  POSTGIS_RT_DEBUG(3, "using pixel method");
2686 
2687  /* pass everything to iterator */
2688  noerr = rt_raster_iterator(
2689  itrset, 2,
2690  ET_UNION, NULL,
2691  pixtype,
2692  hasnodata, nodataval,
2693  0, 0,
2694  NULL,
2695  &utype,
2697  &_raster
2698  );
2699 
2700  if (noerr != ES_NONE) {
2701 
2702  pfree(itrset);
2704  if (raster != NULL) {
2705  rt_raster_destroy(raster);
2706  PG_FREE_IF_COPY(pgraster, 1);
2707  }
2708 
2709  MemoryContextSwitchTo(oldcontext);
2710  elog(ERROR, "RASTER_union_transfn: Could not run raster iterator function");
2711  PG_RETURN_NULL();
2712  }
2713  }
2714 
2715  /* replace working raster */
2716  if (iwr->bandarg[i].raster[j] != NULL && !reuserast) {
2717  for (k = rt_raster_get_num_bands(iwr->bandarg[i].raster[j]) - 1; k >= 0; k--)
2719  rt_raster_destroy(iwr->bandarg[i].raster[j]);
2720  }
2721  iwr->bandarg[i].raster[j] = _raster;
2722  }
2723 
2724  }
2725 
2726  pfree(itrset);
2727  if (raster != NULL) {
2728  rt_raster_destroy(raster);
2729  PG_FREE_IF_COPY(pgraster, 1);
2730  }
2731 
2732  /* switch back to local context */
2733  MemoryContextSwitchTo(oldcontext);
2734 
2735  POSTGIS_RT_DEBUG(3, "Finished");
2736 
2737  PG_RETURN_POINTER(iwr);
2738 }
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition: rt_raster.c:372
rtpg_union_band_arg bandarg
rtpg_union_type
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_raster.c:706
static int rtpg_union_unionarg_process(rtpg_union_arg arg, ArrayType *array)
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:3465
int rt_util_same_geotransform_matrix(double *gt1, double *gt2)
Definition: rt_util.c:487
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:185
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition: rt_band.c:242
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:65
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1597
tuple nband
Definition: pixval.py:52
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_errorstate rt_band_get_pixel_line(rt_band band, int x, int y, uint16_t len, void **vals, uint16_t *nvals)
Get values of multiple pixels.
Definition: rt_band.c:1004
rt_raster rt_raster_clone(rt_raster raster, uint8_t deep)
Clone an existing raster.
Definition: rt_raster.c:1544
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
static int rtpg_union_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
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_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
rt_raster raster
Definition: librtcore.h:2394
static int rtpg_union_noarg(rtpg_union_arg arg, rt_raster raster)
uint16_t nband
Definition: librtcore.h:2395
static void rtpg_union_arg_destroy(rtpg_union_arg arg)
static rtpg_union_type rtpg_uniontype_index_from_name(const char *cutype)
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_raster.c:121
#define FALSE
Definition: dbfopen.c:168
uint8_t nbnodata
Definition: librtcore.h:2396
Struct definitions.
Definition: librtcore.h:2201
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
Definition: rt_band.c:1612
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
rt_errorstate rt_raster_iterator(rt_iterator itrset, uint16_t itrcount, rt_extenttype extenttype, rt_raster customextent, rt_pixtype pixtype, uint8_t hasnodata, double nodataval, uint16_t distancex, uint16_t distancey, rt_mask mask, void *userarg, int(*callback)(rt_iterator_arg arg, void *userarg, double *value, int *nodata), rt_raster *rtnraster)
n-raster iterator.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:498
rt_errorstate rt_band_set_pixel_line(rt_band band, int x, int y, void *vals, uint32_t len)
Set values of multiple pixels.
Definition: rt_band.c:720
struct rtpg_union_arg_t * rtpg_union_arg
rtpg_union_type uniontype
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_raster.c:129
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:717
tuple y
Definition: pixval.py:54
char * rtpg_strtoupper(char *str)

Here is the call graph for this function: