2080{
2081 MemoryContext aggcontext;
2082 MemoryContext oldcontext;
2084 int skiparg = 0;
2085
2091 int noerr = 1;
2092 int isempty[2] = {0};
2093 int hasband[2] = {0};
2094 int nargs = 0;
2095 double _offset[4] = {0.};
2096 int nbnodata = 0;
2097
2098 int i = 0;
2099 int j = 0;
2100 int k = 0;
2101
2103 char *utypename = NULL;
2106 int hasnodata = 1;
2107 double nodataval = 0;
2108
2111 int reuserast = 0;
2113 uint16_t _dim[2] = {0};
2114 void *vals = NULL;
2115 uint16_t nvals = 0;
2116
2118
2119
2120 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
2121 elog(ERROR, "RASTER_union_transfn: Cannot be called in a non-aggregate context");
2122 PG_RETURN_NULL();
2123 }
2124
2125
2126 oldcontext = MemoryContextSwitchTo(aggcontext);
2127
2128 if (PG_ARGISNULL(0)) {
2130
2132 if (iwr == NULL) {
2133 MemoryContextSwitchTo(oldcontext);
2134 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for state variable");
2135 PG_RETURN_NULL();
2136 }
2137
2140
2141 skiparg = 0;
2142 }
2143 else {
2146 skiparg = 1;
2147 }
2148
2149
2150 if (!PG_ARGISNULL(1)) {
2151
2152 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
2153
2154
2156 if (raster == NULL) {
2157
2159 PG_FREE_IF_COPY(pgraster, 1);
2160
2161 MemoryContextSwitchTo(oldcontext);
2162 elog(ERROR, "RASTER_union_transfn: Could not deserialize raster");
2163 PG_RETURN_NULL();
2164 }
2165 }
2166
2167
2168 nargs = PG_NARGS();
2170 if (nargs > 2) {
2172
2173
2174
2175 if (!PG_ARGISNULL(2)) {
2176 Oid calltype = get_fn_expr_argtype(fcinfo->flinfo, 2);
2177
2178 switch (calltype) {
2179
2180 case TEXTOID: {
2181 int idx = 0;
2182 int numband = 0;
2183
2185 nbnodata = 1;
2186
2187 utypename = text_to_cstring(PG_GETARG_TEXT_P(2));
2190
2192
2193 if (raster) {
2197
2198
2201 }
2202
2207
2208
2210
2211 if (numband > idx) {
2214 }
2215
2216 else
2218 }
2219
2220 else {
2223 }
2225
2227 if (raster != NULL) {
2229 PG_FREE_IF_COPY(pgraster, 1);
2230 }
2231
2232 MemoryContextSwitchTo(oldcontext);
2233 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for band information");
2234 PG_RETURN_NULL();
2235 }
2236
2237
2238 for (i = idx; i < iwr->
numband; i++) {
2241
2242 if (
2245 ) {
2247 }
2248 else
2251 }
2252
2253 break;
2254 }
2255
2256 case INT2OID:
2257 case INT4OID:
2258 if (skiparg)
2259 break;
2260
2262 nband = PG_GETARG_INT32(2);
2263 if (nband < 1) {
2264
2266 if (raster != NULL) {
2268 PG_FREE_IF_COPY(pgraster, 1);
2269 }
2270
2271 MemoryContextSwitchTo(oldcontext);
2272 elog(ERROR, "RASTER_union_transfn: Band number must be greater than zero (1-based)");
2273 PG_RETURN_NULL();
2274 }
2275
2279
2281 if (raster != NULL) {
2283 PG_FREE_IF_COPY(pgraster, 1);
2284 }
2285
2286 MemoryContextSwitchTo(oldcontext);
2287 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for band information");
2288 PG_RETURN_NULL();
2289 }
2290
2293
2296 break;
2297
2298 default:
2299 if (skiparg)
2300 break;
2301
2304
2306 if (raster != NULL) {
2308 PG_FREE_IF_COPY(pgraster, 1);
2309 }
2310
2311 MemoryContextSwitchTo(oldcontext);
2312 elog(ERROR, "RASTER_union_transfn: Could not process unionarg");
2313 PG_RETURN_NULL();
2314 }
2315
2316 break;
2317 }
2318 }
2319
2320
2321 if (nargs > 3 && !PG_ARGISNULL(3)) {
2322 utypename = text_to_cstring(PG_GETARG_TEXT_P(3));
2326
2327 if (
2330 ) {
2332 }
2333 }
2334
2335
2336 for (i = 0; i < iwr->
numband; i++) {
2338
2339
2341 continue;
2342
2344
2347
2349 if (raster != NULL) {
2351 PG_FREE_IF_COPY(pgraster, 1);
2352 }
2353
2354 MemoryContextSwitchTo(oldcontext);
2355 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for working raster(s)");
2356 PG_RETURN_NULL();
2357 }
2358
2360
2361
2366
2368 if (raster != NULL) {
2370 PG_FREE_IF_COPY(pgraster, 1);
2371 }
2372
2373 MemoryContextSwitchTo(oldcontext);
2374 elog(ERROR, "RASTER_union_transfn: Could not create working raster");
2375 PG_RETURN_NULL();
2376 }
2377 }
2378 }
2379 }
2380 }
2381
2382
2383 else {
2385 nbnodata = 1;
2387
2389 if (raster != NULL) {
2391 PG_FREE_IF_COPY(pgraster, 1);
2392 }
2393
2394 MemoryContextSwitchTo(oldcontext);
2395 elog(ERROR, "RASTER_union_transfn: Could not check and balance number of bands");
2396 PG_RETURN_NULL();
2397 }
2398 }
2399
2400
2402 if (itrset == NULL) {
2403
2405 if (raster != NULL) {
2407 PG_FREE_IF_COPY(pgraster, 1);
2408 }
2409
2410 MemoryContextSwitchTo(oldcontext);
2411 elog(ERROR, "RASTER_union_transfn: Could not allocate memory for iterator arguments");
2412 PG_RETURN_NULL();
2413 }
2414
2415
2416 for (i = 0; i < iwr->
numband; i++) {
2417
2418
2420 reuserast = 0;
2421
2422
2424
2425
2428
2429 if (!isempty[0])
2431 if (!isempty[1])
2433
2434
2435 _band = NULL;
2436 if (!isempty[0] && hasband[0])
2438 else if (!isempty[1] && hasband[1])
2440 else {
2442 hasnodata = 1;
2444 }
2445 if (_band != NULL) {
2447 hasnodata = 1;
2450 else
2452 }
2453
2454
2455
2457
2458 if (j < 1)
2460 else
2462 }
2463
2465
2466 if (j < 1)
2468 else
2470 }
2471
2472
2475 hasnodata = 0;
2476 nodataval = 0;
2477 }
2478
2480
2481
2483 itrset[0].
nband = 0;
2486
2487
2488 if (nbnodata) {
2491 }
2492
2493 else {
2496 }
2497
2498
2499 if (!isempty[0] && !isempty[1] && hasband[0] && hasband[1]) {
2501
2502
2506 &iraster, _offset
2508
2509 pfree(itrset);
2511 if (raster != NULL) {
2513 PG_FREE_IF_COPY(pgraster, 1);
2514 }
2515
2516 MemoryContextSwitchTo(oldcontext);
2517 elog(ERROR, "RASTER_union_transfn: Could not create internal raster");
2518 PG_RETURN_NULL();
2519 }
2521 _offset[0], _offset[1], _offset[2], _offset[3]);
2522
2523
2524 if (
2527 ) {
2528 double igt[6] = {0};
2530
2533
2535 }
2536
2537
2538 if (!reuserast) {
2539
2541 iraster,
2542 pixtype,
2543 nodataval,
2544 hasnodata, nodataval,
2545 0
2546 ) == -1) {
2547
2548 pfree(itrset);
2551 if (raster != NULL) {
2553 PG_FREE_IF_COPY(pgraster, 1);
2554 }
2555
2556 MemoryContextSwitchTo(oldcontext);
2557 elog(ERROR, "RASTER_union_transfn: Could not add new band to internal raster");
2558 PG_RETURN_NULL();
2559 }
2561
2562
2565 for (y = 0;
y < _dim[1];
y++) {
2566 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of working raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2568 _band,
2569 0, y,
2570 _dim[0],
2571 &vals, &nvals
2573
2574 pfree(itrset);
2578 if (raster != NULL) {
2580 PG_FREE_IF_COPY(pgraster, 1);
2581 }
2582
2583 MemoryContextSwitchTo(oldcontext);
2584 elog(ERROR, "RASTER_union_transfn: Could not get pixel line from band of working raster");
2585 PG_RETURN_NULL();
2586 }
2587
2588 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[0], (
int) _offset[1] + y, nvals);
2590 iband,
2591 (int) _offset[0], (int) _offset[1] + y,
2592 vals, nvals
2594
2595 pfree(itrset);
2599 if (raster != NULL) {
2601 PG_FREE_IF_COPY(pgraster, 1);
2602 }
2603
2604 MemoryContextSwitchTo(oldcontext);
2605 elog(ERROR, "RASTER_union_transfn: Could not set pixel line to band of internal raster");
2606 PG_RETURN_NULL();
2607 }
2608 }
2609 }
2610 else {
2614 }
2615
2616
2618 itrset, 2,
2620 pixtype,
2621 hasnodata, nodataval,
2622 0, 0,
2623 NULL,
2624 &utype,
2626 &_raster
2627 );
2629
2630 pfree(itrset);
2632 if (!reuserast) {
2635 }
2636 if (raster != NULL) {
2638 PG_FREE_IF_COPY(pgraster, 1);
2639 }
2640
2641 MemoryContextSwitchTo(oldcontext);
2642 elog(ERROR, "RASTER_union_transfn: Could not run raster iterator function");
2643 PG_RETURN_NULL();
2644 }
2645
2646
2650 for (y = 0;
y < _dim[1];
y++) {
2651 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of iterator raster at (x, y, length) = (0, %d, %d)", y, _dim[0]);
2653 _band,
2654 0, y,
2655 _dim[0],
2656 &vals, &nvals
2658
2659 pfree(itrset);
2661 if (!reuserast) {
2664 }
2665 if (raster != NULL) {
2667 PG_FREE_IF_COPY(pgraster, 1);
2668 }
2669
2670 MemoryContextSwitchTo(oldcontext);
2671 elog(ERROR, "RASTER_union_transfn: Could not get pixel line from band of working raster");
2672 PG_RETURN_NULL();
2673 }
2674
2675 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[2], (
int) _offset[3] + y, nvals);
2677 iband,
2678 (int) _offset[2], (int) _offset[3] + y,
2679 vals, nvals
2681
2682 pfree(itrset);
2684 if (!reuserast) {
2687 }
2688 if (raster != NULL) {
2690 PG_FREE_IF_COPY(pgraster, 1);
2691 }
2692
2693 MemoryContextSwitchTo(oldcontext);
2694 elog(ERROR, "RASTER_union_transfn: Could not set pixel line to band of internal raster");
2695 PG_RETURN_NULL();
2696 }
2697 }
2698
2699
2702
2703
2704 _raster = iraster;
2705 }
2706 else {
2708
2709
2711 itrset, 2,
2713 pixtype,
2714 hasnodata, nodataval,
2715 0, 0,
2716 NULL,
2717 &utype,
2719 &_raster
2720 );
2721
2723
2724 pfree(itrset);
2726 if (raster != NULL) {
2728 PG_FREE_IF_COPY(pgraster, 1);
2729 }
2730
2731 MemoryContextSwitchTo(oldcontext);
2732 elog(ERROR, "RASTER_union_transfn: Could not run raster iterator function");
2733 PG_RETURN_NULL();
2734 }
2735 }
2736
2737
2742 }
2744 }
2745
2746 }
2747
2748 pfree(itrset);
2749 if (raster != NULL) {
2751 PG_FREE_IF_COPY(pgraster, 1);
2752 }
2753
2754
2755 MemoryContextSwitchTo(oldcontext);
2756
2758
2759 PG_RETURN_POINTER(iwr);
2760}
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 * 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