2115{
2116 MemoryContext aggcontext;
2117 MemoryContext oldcontext;
2119 int skiparg = 0;
2120
2126 int noerr = 1;
2127 int isempty[2] = {0};
2128 int hasband[2] = {0};
2129 int nargs = 0;
2130 double _offset[4] = {0.};
2131 int nbnodata = 0;
2132
2133 int i = 0;
2134 int j = 0;
2135 int k = 0;
2136
2138 char *utypename = NULL;
2141 int hasnodata = 1;
2142 double nodataval = 0;
2143
2146 int reuserast = 0;
2148 uint16_t _dim[2] = {0};
2149 void *vals = NULL;
2150 uint16_t nvals = 0;
2151
2153
2154
2155 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
2156 elog(ERROR, "RASTER_union_transfn: Cannot be called in a non-aggregate context");
2157 PG_RETURN_NULL();
2158 }
2159
2160
2161 oldcontext = MemoryContextSwitchTo(aggcontext);
2162
2163 if (PG_ARGISNULL(0)) {
2165
2167 if (iwr == NULL) {
2168 MemoryContextSwitchTo(oldcontext);
2169 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for state variable");
2170 PG_RETURN_NULL();
2171 }
2172
2175
2176 skiparg = 0;
2177 }
2178 else {
2181 skiparg = 1;
2182 }
2183
2184
2185 if (!PG_ARGISNULL(1)) {
2186
2187 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
2188
2189
2191 if (raster == NULL) {
2192
2194 PG_FREE_IF_COPY(pgraster, 1);
2195
2196 MemoryContextSwitchTo(oldcontext);
2197 elog(ERROR, "RASTER_union_transfn: Could not deserialize raster");
2198 PG_RETURN_NULL();
2199 }
2200 }
2201
2202
2203 nargs = PG_NARGS();
2205 if (nargs > 2) {
2207
2208
2209
2210 if (!PG_ARGISNULL(2)) {
2211 Oid calltype = get_fn_expr_argtype(fcinfo->flinfo, 2);
2212
2213 switch (calltype) {
2214
2215 case TEXTOID: {
2216 int idx = 0;
2217 int numband = 0;
2218
2220 nbnodata = 1;
2221
2225
2227
2228 if (raster) {
2232
2233
2236 }
2237
2242
2243
2245
2246 if (numband > idx) {
2249 }
2250
2251 else
2253 }
2254
2255 else {
2258 }
2260
2262 if (raster != NULL) {
2264 PG_FREE_IF_COPY(pgraster, 1);
2265 }
2266
2267 MemoryContextSwitchTo(oldcontext);
2268 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for band information");
2269 PG_RETURN_NULL();
2270 }
2271
2272
2273 for (i = idx; i < iwr->
numband; i++) {
2276
2277 if (
2280 ) {
2282 }
2283 else
2286 }
2287
2288 break;
2289 }
2290
2291 case INT2OID:
2292 case INT4OID:
2293 if (skiparg)
2294 break;
2295
2297 nband = PG_GETARG_INT32(2);
2298 if (nband < 1) {
2299
2301 if (raster != NULL) {
2303 PG_FREE_IF_COPY(pgraster, 1);
2304 }
2305
2306 MemoryContextSwitchTo(oldcontext);
2307 elog(ERROR, "RASTER_union_transfn: Band number must be greater than zero (1-based)");
2308 PG_RETURN_NULL();
2309 }
2310
2314
2316 if (raster != NULL) {
2318 PG_FREE_IF_COPY(pgraster, 1);
2319 }
2320
2321 MemoryContextSwitchTo(oldcontext);
2322 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for band information");
2323 PG_RETURN_NULL();
2324 }
2325
2328
2331 break;
2332
2333 default:
2334 if (skiparg)
2335 break;
2336
2339
2341 if (raster != NULL) {
2343 PG_FREE_IF_COPY(pgraster, 1);
2344 }
2345
2346 MemoryContextSwitchTo(oldcontext);
2347 elog(ERROR, "RASTER_union_transfn: Could not process unionarg");
2348 PG_RETURN_NULL();
2349 }
2350
2351 break;
2352 }
2353 }
2354
2355
2356 if (nargs > 3 && !PG_ARGISNULL(3)) {
2361
2362 if (
2365 ) {
2367 }
2368 }
2369
2370
2371 for (i = 0; i < iwr->
numband; i++) {
2373
2374
2376 continue;
2377
2379
2382
2384 if (raster != NULL) {
2386 PG_FREE_IF_COPY(pgraster, 1);
2387 }
2388
2389 MemoryContextSwitchTo(oldcontext);
2390 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for working raster(s)");
2391 PG_RETURN_NULL();
2392 }
2393
2395
2396
2401
2403 if (raster != NULL) {
2405 PG_FREE_IF_COPY(pgraster, 1);
2406 }
2407
2408 MemoryContextSwitchTo(oldcontext);
2409 elog(ERROR, "RASTER_union_transfn: Could not create working raster");
2410 PG_RETURN_NULL();
2411 }
2412 }
2413 }
2414 }
2415 }
2416
2417
2418 else {
2420 nbnodata = 1;
2422
2424 if (raster != NULL) {
2426 PG_FREE_IF_COPY(pgraster, 1);
2427 }
2428
2429 MemoryContextSwitchTo(oldcontext);
2430 elog(ERROR, "RASTER_union_transfn: Could not check and balance number of bands");
2431 PG_RETURN_NULL();
2432 }
2433 }
2434
2435
2437 if (itrset == NULL) {
2438
2440 if (raster != NULL) {
2442 PG_FREE_IF_COPY(pgraster, 1);
2443 }
2444
2445 MemoryContextSwitchTo(oldcontext);
2446 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for iterator arguments");
2447 PG_RETURN_NULL();
2448 }
2449
2450
2451 for (i = 0; i < iwr->
numband; i++) {
2452
2453
2455 reuserast = 0;
2456
2457
2459
2460
2463
2464 if (!isempty[0])
2466 if (!isempty[1])
2468
2469
2470 _band = NULL;
2471 if (!isempty[0] && hasband[0])
2473 else if (!isempty[1] && hasband[1])
2475 else {
2477 hasnodata = 1;
2479 }
2480 if (_band != NULL) {
2482 hasnodata = 1;
2485 else
2487 }
2488
2489
2490
2492
2493 if (j < 1)
2495 else
2497 }
2498
2500
2501 if (j < 1)
2503 else
2505 }
2506
2507
2510 hasnodata = 0;
2511 nodataval = 0;
2512 }
2513
2515
2516
2518 itrset[0].
nband = 0;
2521
2522
2523 if (nbnodata) {
2526 }
2527
2528 else {
2531 }
2532
2533
2534 if (!isempty[0] && !isempty[1] && hasband[0] && hasband[1]) {
2536
2537
2541 &iraster, _offset
2543
2544 pfree(itrset);
2546 if (raster != NULL) {
2548 PG_FREE_IF_COPY(pgraster, 1);
2549 }
2550
2551 MemoryContextSwitchTo(oldcontext);
2552 elog(ERROR, "RASTER_union_transfn: Could not create internal raster");
2553 PG_RETURN_NULL();
2554 }
2556 _offset[0], _offset[1], _offset[2], _offset[3]);
2557
2558
2559 if (
2562 ) {
2563 double igt[6] = {0};
2565
2568
2570 }
2571
2572
2573 if (!reuserast) {
2574
2576 iraster,
2577 pixtype,
2578 nodataval,
2579 hasnodata, nodataval,
2580 0
2581 ) == -1) {
2582
2583 pfree(itrset);
2586 if (raster != NULL) {
2588 PG_FREE_IF_COPY(pgraster, 1);
2589 }
2590
2591 MemoryContextSwitchTo(oldcontext);
2592 elog(ERROR, "RASTER_union_transfn: Could not add new band to internal raster");
2593 PG_RETURN_NULL();
2594 }
2596
2597
2600 for (y = 0;
y < _dim[1];
y++) {
2601 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of working raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2603 _band,
2604 0, y,
2605 _dim[0],
2606 &vals, &nvals
2608
2609 pfree(itrset);
2613 if (raster != NULL) {
2615 PG_FREE_IF_COPY(pgraster, 1);
2616 }
2617
2618 MemoryContextSwitchTo(oldcontext);
2619 elog(ERROR, "RASTER_union_transfn: Could not get pixel line from band of working raster");
2620 PG_RETURN_NULL();
2621 }
2622
2623 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[0], (
int) _offset[1] + y, nvals);
2625 iband,
2626 (int) _offset[0], (int) _offset[1] + y,
2627 vals, nvals
2629
2630 pfree(itrset);
2634 if (raster != NULL) {
2636 PG_FREE_IF_COPY(pgraster, 1);
2637 }
2638
2639 MemoryContextSwitchTo(oldcontext);
2640 elog(ERROR, "RASTER_union_transfn: Could not set pixel line to band of internal raster");
2641 PG_RETURN_NULL();
2642 }
2643 }
2644 }
2645 else {
2649 }
2650
2651
2653 itrset, 2,
2655 pixtype,
2656 hasnodata, nodataval,
2657 0, 0,
2658 NULL,
2659 &utype,
2661 &_raster
2662 );
2664
2665 pfree(itrset);
2667 if (!reuserast) {
2670 }
2671 if (raster != NULL) {
2673 PG_FREE_IF_COPY(pgraster, 1);
2674 }
2675
2676 MemoryContextSwitchTo(oldcontext);
2677 elog(ERROR, "RASTER_union_transfn: Could not run raster iterator function");
2678 PG_RETURN_NULL();
2679 }
2680
2681
2685 for (y = 0;
y < _dim[1];
y++) {
2686 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of iterator raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2688 _band,
2689 0, y,
2690 _dim[0],
2691 &vals, &nvals
2693
2694 pfree(itrset);
2696 if (!reuserast) {
2699 }
2700 if (raster != NULL) {
2702 PG_FREE_IF_COPY(pgraster, 1);
2703 }
2704
2705 MemoryContextSwitchTo(oldcontext);
2706 elog(ERROR, "RASTER_union_transfn: Could not get pixel line from band of working raster");
2707 PG_RETURN_NULL();
2708 }
2709
2710 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[2], (
int) _offset[3] + y, nvals);
2712 iband,
2713 (int) _offset[2], (int) _offset[3] + y,
2714 vals, nvals
2716
2717 pfree(itrset);
2719 if (!reuserast) {
2722 }
2723 if (raster != NULL) {
2725 PG_FREE_IF_COPY(pgraster, 1);
2726 }
2727
2728 MemoryContextSwitchTo(oldcontext);
2729 elog(ERROR, "RASTER_union_transfn: Could not set pixel line to band of internal raster");
2730 PG_RETURN_NULL();
2731 }
2732 }
2733
2734
2737
2738
2739 _raster = iraster;
2740 }
2741 else {
2743
2744
2746 itrset, 2,
2748 pixtype,
2749 hasnodata, nodataval,
2750 0, 0,
2751 NULL,
2752 &utype,
2754 &_raster
2755 );
2756
2758
2759 pfree(itrset);
2761 if (raster != NULL) {
2763 PG_FREE_IF_COPY(pgraster, 1);
2764 }
2765
2766 MemoryContextSwitchTo(oldcontext);
2767 elog(ERROR, "RASTER_union_transfn: Could not run raster iterator function");
2768 PG_RETURN_NULL();
2769 }
2770 }
2771
2772
2777 }
2779 }
2780
2781 }
2782
2783 pfree(itrset);
2784 if (raster != NULL) {
2786 PG_FREE_IF_COPY(pgraster, 1);
2787 }
2788
2789
2790 MemoryContextSwitchTo(oldcontext);
2791
2793
2794 PG_RETURN_POINTER(iwr);
2795}
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.
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
const char * rt_pixtype_name(rt_pixtype pixtype)
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
rt_errorstate rt_band_set_pixel_line(rt_band band, int x, int y, void *vals, uint32_t len)
Set values of multiple pixels.
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
rt_raster rt_raster_clone(rt_raster raster, uint8_t deep)
Clone an existing raster.
uint16_t rt_raster_get_height(rt_raster raster)
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_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
uint16_t rt_raster_get_width(rt_raster raster)
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
int rt_util_same_geotransform_matrix(double *gt1, double *gt2)
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
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.
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
char * text_to_cstring(const text *textptr)
char * rtpg_strtoupper(char *str)
static rtpg_union_type rtpg_uniontype_index_from_name(const char *cutype)
static void rtpg_union_arg_destroy(rtpg_union_arg arg)
struct rtpg_union_arg_t * rtpg_union_arg
static int rtpg_union_unionarg_process(rtpg_union_arg arg, ArrayType *array)
static int rtpg_union_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
static int rtpg_union_noarg(rtpg_union_arg arg, rt_raster raster)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)
rtpg_union_band_arg bandarg
rtpg_union_type uniontype