Compute summary statistics for a band.
115 {
118 uint32_t z = 0;
119 uint32_t offset = 0;
120 uint32_t diff = 0;
121 int rtn;
122 int hasnodata =
FALSE;
123 double nodata = 0;
124 double *values = NULL;
126 int isnodata = 0;
128
129 uint32_t do_sample = 0;
130 uint32_t sample_size = 0;
131 uint32_t sample_per = 0;
132 uint32_t sample_int = 0;
133 uint32_t i = 0;
134 uint32_t j = 0;
135 double sum = 0;
136 uint32_t k = 0;
137 double M = 0;
138 double Q = 0;
139
140#if POSTGIS_DEBUG_LEVEL > 0
141 clock_t start, stop;
142 double elapsed = 0;
143#endif
144
146#if POSTGIS_DEBUG_LEVEL > 0
147 start = clock();
148#endif
149
150 assert(NULL != band);
151
152
153 if (
band->width < 1 ||
band->height < 1) {
155 if (NULL == stats) {
156 rterror(
"rt_band_get_summary_stats: Could not allocate memory for stats");
157 return NULL;
158 }
159
160 rtwarn(
"Band is empty as width and/or height is 0");
161
166 stats->
min = stats->
max = 0;
170
171 return stats;
172 }
173
175 if (hasnodata !=
FALSE)
177 else
178 exclude_nodata_value = 0;
179
182 RASTER_DEBUGF(3,
"exclude_nodata_value = %d", exclude_nodata_value);
183
184
187 if (NULL == stats) {
188 rterror(
"rt_band_get_summary_stats: Could not allocate memory for stats");
189 return NULL;
190 }
191
195
196 if (exclude_nodata_value) {
197 rtwarn(
"All pixels of band have the NODATA value");
198
200 stats->
min = stats->
max = 0;
204 }
205 else {
207 stats->
min = stats->
max = nodata;
209 stats->
mean = nodata;
211 }
212
213 return stats;
214 }
215
216
217 if (
218 (sample < 0 ||
FLT_EQ(sample, 0.0)) ||
219 (sample > 1 ||
FLT_EQ(sample, 1.0))
220 ) {
221 do_sample = 0;
222 sample = 1;
223 }
224 else
225 do_sample = 1;
227
228
229 if (!do_sample) {
230 sample_size =
band->width *
band->height;
231 sample_per =
band->height;
232 }
233
234
235
236
237
238 else {
239 sample_size = round((
band->width *
band->height) * sample);
240 sample_per = round(sample_size /
band->width);
241 if (sample_per < 1)
242 sample_per = 1;
243 sample_int = round(
band->height / sample_per);
244 srand(time(NULL));
245 }
246
247 RASTER_DEBUGF(3,
"sampling %d of %d available pixels w/ %d per set"
248 , sample_size, (
band->width *
band->height), sample_per);
249
250 if (inc_vals) {
251 values =
rtalloc(
sizeof(
double) * sample_size);
252 if (NULL == values) {
253 rtwarn(
"Could not allocate memory for values");
254 inc_vals = 0;
255 }
256 }
257
258
260 if (NULL == stats) {
261 rterror(
"rt_band_get_summary_stats: Could not allocate memory for stats");
262 return NULL;
263 }
269 stats->
min = stats->
max = 0;
272
273 for (x = 0, j = 0, k = 0;
x <
band->width;
x++) {
275 diff = 0;
276
277 for (i = 0, z = 0; i < sample_per; i++) {
278 if (!do_sample)
280 else {
281 offset = (rand() % sample_int) + 1;
283 diff = sample_int - offset;
284 }
286 if (y >=
band->height || z > sample_per)
break;
287
289
290 j++;
291 if (rtn ==
ES_NONE && (!exclude_nodata_value || (exclude_nodata_value && !isnodata))) {
292
293
294 if (inc_vals) values[k] =
value;
295
296
297 k++;
299
300
301
302
303
304 if (k == 1) {
305 Q = 0;
307 }
308 else {
309 Q += (((k - 1) * pow(value - M, 2)) / k);
310 M += ((
value - M ) / k);
311 }
312
313
314 if (NULL != cK) {
315 (*cK)++;
316 if (*cK == 1) {
317 *cQ = 0;
319 }
320 else {
321 *cQ += (((*cK - 1) * pow(value - *cM, 2)) / *cK);
322 *cM += ((
value - *cM ) / *cK);
323 }
324 }
325
326
327 if (stats->
count < 1) {
330 }
331 else {
332 if (value < stats->min)
334 if (value > stats->
max)
336 }
337
338 }
339
340 z++;
341 }
342 }
343
345
347 if (k > 0) {
348 if (inc_vals) {
349
350 if (sample_size != k) {
351 values =
rtrealloc(values, k *
sizeof(
double));
352 }
353
355 }
356
358 stats->
mean = sum / k;
359
360
361 if (!do_sample)
362 stats->
stddev = sqrt(Q / k);
363
364 else {
365 if (k < 2)
367 else
368 stats->
stddev = sqrt(Q / (k - 1));
369 }
370 }
371
372 else if (inc_vals)
374
375
376 if (do_sample && k < 1)
377 rtwarn(
"All sampled pixels of band have the NODATA value");
378
379#if POSTGIS_DEBUG_LEVEL > 0
380 stop = clock();
381 elapsed = ((double) (stop - start)) / CLOCKS_PER_SEC;
382 RASTER_DEBUGF(3,
"(time, count, mean, stddev, min, max) = (%0.4f, %d, %f, %f, %f, %f)",
384#endif
385
387 return stats;
388}
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
#define RASTER_DEBUG(level, msg)
#define RASTER_DEBUGF(level, msg,...)
void void void rtwarn(const char *fmt,...) __attribute__((format(printf
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
struct rt_bandstats_t * rt_bandstats
void * rtrealloc(void *mem, size_t size)
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
void rtdealloc(void *mem)