PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ RASTER_addBand()

Datum RASTER_addBand ( PG_FUNCTION_ARGS  )

Definition at line 121 of file rtpg_create.c.

122{
123 rt_pgraster *pgraster = NULL;
124 rt_pgraster *pgrtn = NULL;
125 rt_raster raster = NULL;
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;
137 rt_pixtype pixtype;
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 /* pgraster is null, return null */
160 if (PG_ARGISNULL(0))
161 PG_RETURN_NULL();
162 pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
163
164 /* raster */
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 /* process set of addbandarg */
173 POSTGIS_RT_DEBUG(3, "Processing Arg 1 (addbandargset)");
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 /* allocate addbandarg */
188 arg = (struct addbandarg *) palloc(sizeof(struct addbandarg) * n);
189 if (arg == NULL) {
190 rt_raster_destroy(raster);
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 process each element of addbandargset
198 each element is the index of where to add the new band,
199 new band's pixeltype, the new band's initial value and
200 the new band's NODATA value if NOT NULL
201 */
202 for (i = 0; i < n; i++) {
203 if (nulls[i]) continue;
204
205 POSTGIS_RT_DEBUGF(4, "Processing addbandarg at index %d", i);
206
207 /* each element is a tuple */
208 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
209 if (NULL == tup) {
210 pfree(arg);
211 rt_raster_destroy(raster);
212 PG_FREE_IF_COPY(pgraster, 0);
213 elog(ERROR, "RASTER_addBand: Invalid argument for addbandargset");
214 PG_RETURN_NULL();
215 }
216
217 /* new band index, 1-based */
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 /* for now, only check that band index is 1-based */
227 if (!arg[i].append && arg[i].index < 1) {
228 pfree(arg);
229 rt_raster_destroy(raster);
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 /* new band pixeltype */
236 arg[i].pixtype = PT_END;
237 tupv = GetAttributeByName(tup, "pixeltype", &isnull);
238 if (isnull) {
239 pfree(arg);
240 rt_raster_destroy(raster);
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);
248 rt_raster_destroy(raster);
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
255 arg[i].pixtype = rt_pixtype_index_from_name(char_pixtype);
256 pfree(char_pixtype);
257 if (arg[i].pixtype == PT_END) {
258 pfree(arg);
259 rt_raster_destroy(raster);
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 /* new band initialvalue */
266 arg[i].initialvalue = 0;
267 tupv = GetAttributeByName(tup, "initialvalue", &isnull);
268 if (!isnull)
269 arg[i].initialvalue = DatumGetFloat8(tupv);
270
271 /* new band NODATA value */
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 /* add new bands to raster */
282 lastnumbands = rt_raster_get_num_bands(raster);
283 for (i = 0; i < n; i++) {
284 if (nulls[i]) continue;
285
286 POSTGIS_RT_DEBUGF(3, "%d bands in old raster", lastnumbands);
287 maxbandindex = lastnumbands + 1;
288
289 /* check that new band's index doesn't exceed maxbandindex */
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 /* append, so use maxbandindex */
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,
302 rt_pixtype_name(arg[i].pixtype),
303 arg[i].initialvalue,
304 arg[i].hasnodata ? "TRUE" : "FALSE",
305 arg[i].nodatavalue
306 );
307
308 bandindex = rt_raster_generate_new_band(
309 raster,
310 arg[i].pixtype, arg[i].initialvalue,
311 arg[i].hasnodata, arg[i].nodatavalue,
312 arg[i].index - 1
313 );
314
315 numbands = rt_raster_get_num_bands(raster);
316 if (numbands == lastnumbands || bandindex == -1) {
317 pfree(arg);
318 rt_raster_destroy(raster);
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;
325 POSTGIS_RT_DEBUGF(3, "%d bands in new raster", lastnumbands);
326 }
327
328 pfree(arg);
329
330 pgrtn = rt_raster_serialize(raster);
331 rt_raster_destroy(raster);
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}
#define TRUE
Definition dbfopen.c:73
#define FALSE
Definition dbfopen.c:72
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:489
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition rt_pixel.c:82
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition rt_raster.c:86
rt_pixtype
Definition librtcore.h:188
@ PT_END
Definition librtcore.h:201
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition rt_pixel.c:114
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition rt_raster.c:376
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): ...
Definition rtrowdump.py:125
#define POSTGIS_RT_DEBUG(level, msg)
Definition rtpostgis.h:65
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition rtpostgis.h:69
Struct definitions.
Definition librtcore.h:2452

References FALSE, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, PT_END, rt_pixtype_index_from_name(), rt_pixtype_name(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_generate_new_band(), rt_raster_get_num_bands(), rt_raster_serialize(), rt_raster_serialized_t::size, and TRUE.

Here is the call graph for this function: