int *allnull, int *allempty
) {
int i = 0;
+ int hasband = 0;
_param->count = itrcount;
_param->distance.x = distancex;
}
/* check band number */
- if (!rt_raster_has_band(itrset[i].raster, itrset[i].nband)) {
- rterror("_rti_param_populate: Band %d not found for raster %d", itrset[i].nband, i);
- return 0;
+ hasband = rt_raster_has_band(itrset[i].raster, itrset[i].nband);
+ if (!hasband) {
+ if (!itrset[i].nbnodata) {
+ rterror("_rti_param_populate: Band %d not found for raster %d", itrset[i].nband, i);
+ return 0;
+ }
+ else {
+ RASTER_DEBUGF(4, "Band %d not found for raster %d. Using NODATA", itrset[i].nband, i);
+ }
}
_param->raster[i] = itrset[i].raster;
- _param->band[i] = rt_raster_get_band(itrset[i].raster, itrset[i].nband);
- if (_param->band[i] == NULL) {
- rterror("_rti_param_populate: Unable to get band %d for raster %d", itrset[i].nband, i);
- return 0;
+ if (hasband) {
+ _param->band[i] = rt_raster_get_band(itrset[i].raster, itrset[i].nband);
+ if (_param->band[i] == NULL) {
+ rterror("_rti_param_populate: Unable to get band %d for raster %d", itrset[i].nband, i);
+ return 0;
+ }
}
/* init offset */
);
/* init values and NODATA for use with empty rasters */
- if (allempty > 0 && !_rti_param_empty_init(_param)) {
+ if (!_rti_param_empty_init(_param)) {
rterror("rt_raster_iterator: Unable to initialize empty values and NODATA");
_rti_param_destroy(_param);
RASTER_DEBUGF(4, "raster %d", i);
/* empty raster */
- if (_param->isempty[i]) {
- RASTER_DEBUG(4, "empty raster. using empty values and NODATA");
+ /* OR band does not exist and flag set to use NODATA */
+ if (_param->isempty[i] || (_param->band[i] == NULL && itrset[i].nbnodata)) {
+ RASTER_DEBUG(4, "empty raster or band does not exist. using empty values and NODATA");
x = _x;
y = _y;
}
/* callback */
+ RASTER_DEBUG(4, "calling callback function");
value = 0;
nodata = 0;
status = callback(_param->arg, userarg, &value, &nodata);
struct rt_iterator_t {
rt_raster raster;
uint16_t nband; /* 0-based */
+ uint8_t nbnodata; /* no band = treat as NODATA */
};
/* callback argument from raster iterator */
break;
numbands = rt_raster_get_num_bands(raster);
- if (numbands == iwr->numband)
+ if (numbands <= iwr->numband)
break;
- /* incoming has fewer bands, add NODATA bands to incoming */
- /* TODO: have rt_raster_iterator() treat missing band as NODATA band? */
- if (numbands < iwr->numband) {
- POSTGIS_RT_DEBUG(4, "input raster has fewer bands, adding NODATA bands");
- for (i = numbands; i < iwr->numband; i++) {
- if (rt_raster_generate_new_band(raster, PT_8BUI, 0, 1, 0, i) < 0) {
- elog(ERROR, "RASTER_union_transfn: Unable to create NODATA band");
-
- rtpg_union_arg_destroy(iwr);
- if (raster != NULL) {
- rt_raster_destroy(raster);
- PG_FREE_IF_COPY(pgraster, 1);
- }
-
- MemoryContextSwitchTo(oldcontext);
- PG_RETURN_NULL();
- }
- }
-
- break;
- }
-
/* more bands to process */
POSTGIS_RT_DEBUG(4, "input raster has more bands, adding more bandargs");
if (iwr->numband)
MemoryContextSwitchTo(oldcontext);
PG_RETURN_NULL();
}
-
- /* create band of same type as input raster */
- _band = rt_raster_get_band(raster, i);
- pixtype = rt_band_get_pixtype(_band);
- hasnodata = rt_band_get_hasnodata_flag(_band);
- if (hasnodata)
- nodataval = rt_band_get_nodata(_band);
- else
- nodataval = rt_band_get_min_value(_band);
-
- if (rt_raster_generate_new_band(
- iwr->bandarg[i].raster[0],
- pixtype,
- nodataval,
- hasnodata, nodataval,
- i
- ) < 0) {
- elog(ERROR, "RASTER_union_transfn: Unable to add new band to working raster");
-
- rtpg_union_arg_destroy(iwr);
- if (raster != NULL) {
- rt_raster_destroy(raster);
- PG_FREE_IF_COPY(pgraster, 1);
- }
-
- MemoryContextSwitchTo(oldcontext);
- PG_RETURN_NULL();
- }
}
}
itrset[1].raster = raster;
itrset[1].nband = iwr->bandarg[i].nband;
+ /* no additional arguments in aggregate, allow use NODATA to replace missing bands */
+ if (nargs < 3) {
+ itrset[0].nbnodata = 1;
+ itrset[1].nbnodata = 1;
+ }
+ /* additional arguments in aggregate, missing bands are not ignored */
+ else {
+ itrset[0].nbnodata = 0;
+ itrset[1].nbnodata = 0;
+ }
+
/* pass everything to iterator */
_raster = rt_raster_iterator(
itrset, 2,
itrset = rtalloc(sizeof(struct rt_iterator_t) * num);
itrset[0].raster = rast1;
itrset[0].nband = 0;
+ itrset[0].nbnodata = 1;
itrset[1].raster = rast2;
itrset[1].nband = 0;
+ itrset[1].nbnodata = 1;
/* 1 raster, 0 distance, FIRST or SECOND or LAST or UNION or INTERSECTION */
userargs->rasters = 1;