122{
126 int bandindex = 0;
127 int maxbandindex = 0;
128 int numbands = 0;
129 int lastnumbands = 0;
130
131 text *text_pixtype = NULL;
132 char *char_pixtype = NULL;
133
134 struct addbandarg {
135 int index;
136 bool append;
138 double initialvalue;
139 bool hasnodata;
140 double nodatavalue;
141 };
142 struct addbandarg *arg = NULL;
143
144 ArrayType *array;
145 Oid etype;
146 Datum *e;
147 bool *nulls;
148 int16 typlen;
149 bool typbyval;
150 char typalign;
151 int n = 0;
152
153 HeapTupleHeader tup;
154 bool isnull;
155 Datum tupv;
156
157 int i = 0;
158
159
160 if (PG_ARGISNULL(0))
161 PG_RETURN_NULL();
162 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
163
164
166 if (!raster) {
167 PG_FREE_IF_COPY(pgraster, 0);
168 elog(ERROR, "RASTER_addBand: Could not deserialize raster");
169 PG_RETURN_NULL();
170 }
171
172
174 array = PG_GETARG_ARRAYTYPE_P(1);
175 etype = ARR_ELEMTYPE(array);
176 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
177
178 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
179 &nulls, &n);
180
181 if (!n) {
182 PG_FREE_IF_COPY(pgraster, 0);
183 elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset");
184 PG_RETURN_NULL();
185 }
186
187
188 arg = (struct addbandarg *) palloc(sizeof(struct addbandarg) * n);
189 if (arg == NULL) {
191 PG_FREE_IF_COPY(pgraster, 0);
192 elog(ERROR, "RASTER_addBand: Could not allocate memory for addbandarg");
193 PG_RETURN_NULL();
194 }
195
196
197
198
199
200
201
202 for (i = 0; i < n; i++) {
203 if (nulls[i]) continue;
204
206
207
208 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
209 if (NULL == tup) {
210 pfree(arg);
212 PG_FREE_IF_COPY(pgraster, 0);
213 elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset");
214 PG_RETURN_NULL();
215 }
216
217
218 arg[i].index = 0;
219 arg[i].append =
TRUE;
220 tupv = GetAttributeByName(tup, "index", &isnull);
221 if (!isnull) {
222 arg[i].index = DatumGetInt32(tupv);
223 arg[i].append =
FALSE;
224 }
225
226
227 if (!arg[i].append && arg[i].index < 1) {
228 pfree(arg);
230 PG_FREE_IF_COPY(pgraster, 0);
231 elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Invalid band index (must be 1-based) for addbandarg of index %d", i);
232 PG_RETURN_NULL();
233 }
234
235
237 tupv = GetAttributeByName(tup, "pixeltype", &isnull);
238 if (isnull) {
239 pfree(arg);
241 PG_FREE_IF_COPY(pgraster, 0);
242 elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Pixel type cannot be NULL for addbandarg of index %d", i);
243 PG_RETURN_NULL();
244 }
245 text_pixtype = (text *) DatumGetPointer(tupv);
246 if (text_pixtype == NULL) {
247 pfree(arg);
249 PG_FREE_IF_COPY(pgraster, 0);
250 elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Pixel type cannot be NULL for addbandarg of index %d", i);
251 PG_RETURN_NULL();
252 }
253 char_pixtype = text_to_cstring(text_pixtype);
254
256 pfree(char_pixtype);
257 if (arg[i].pixtype ==
PT_END) {
258 pfree(arg);
260 PG_FREE_IF_COPY(pgraster, 0);
261 elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset. Invalid pixel type for addbandarg of index %d", i);
262 PG_RETURN_NULL();
263 }
264
265
266 arg[i].initialvalue = 0;
267 tupv = GetAttributeByName(tup, "initialvalue", &isnull);
268 if (!isnull)
269 arg[i].initialvalue = DatumGetFloat8(tupv);
270
271
272 arg[i].hasnodata =
FALSE;
273 arg[i].nodatavalue = 0;
274 tupv = GetAttributeByName(tup, "nodataval", &isnull);
275 if (!isnull) {
276 arg[i].hasnodata =
TRUE;
277 arg[i].nodatavalue = DatumGetFloat8(tupv);
278 }
279 }
280
281
283 for (i = 0; i < n; i++) {
284 if (nulls[i]) continue;
285
287 maxbandindex = lastnumbands + 1;
288
289
290 if (!arg[i].append) {
291 if (arg[i].index > maxbandindex) {
292 elog(NOTICE, "Band index for addbandarg of index %d exceeds possible value. Adding band at index %d", i, maxbandindex);
293 arg[i].index = maxbandindex;
294 }
295 }
296
297 else
298 arg[i].index = maxbandindex;
299
300 POSTGIS_RT_DEBUGF(4,
"new band (index, pixtype, initialvalue, hasnodata, nodatavalue) = (%d, %s, %f, %s, %f)",
301 arg[i].index,
303 arg[i].initialvalue,
304 arg[i].hasnodata ? "TRUE" : "FALSE",
305 arg[i].nodatavalue
306 );
307
309 raster,
310 arg[i].pixtype, arg[i].initialvalue,
311 arg[i].hasnodata, arg[i].nodatavalue,
312 arg[i].index - 1
313 );
314
316 if (numbands == lastnumbands || bandindex == -1) {
317 pfree(arg);
319 PG_FREE_IF_COPY(pgraster, 0);
320 elog(ERROR, "RASTER_addBand: Could not add band defined by addbandarg of index %d to raster", i);
321 PG_RETURN_NULL();
322 }
323
324 lastnumbands = numbands;
326 }
327
328 pfree(arg);
329
332 PG_FREE_IF_COPY(pgraster, 0);
333 if (!pgrtn)
334 PG_RETURN_NULL();
335
336 SET_VARSIZE(pgrtn, pgrtn->
size);
337 PG_RETURN_POINTER(pgrtn);
338}
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.
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
const char * rt_pixtype_name(rt_pixtype pixtype)
uint16_t rt_raster_get_num_bands(rt_raster raster)
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)