CR2RE Pipeline Reference Manual 1.6.10
irplib_hist.c
1
2
3/*
4 * This file is part of the irplib package
5 * Copyright (C) 2002, 2003 European Southern Observatory
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
20 */
21
22/*
23 * $Author: jtaylor $
24 * $Id: irplib_hist.c,v 1.8 2013-07-04 12:10:12 jtaylor Exp $
25 * $Date: 2013-07-04 12:10:12 $
26 * $Revision: 1.8 $
27 * $Name: not supported by cvs2svn $
28 */
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#include <stdlib.h>
35#include <stdio.h>
36
37#include <math.h>
38
39#include "irplib_hist.h"
40
41struct _irplib_hist_
42{
43 unsigned long * bins;
44 unsigned long nbins;
45 double start;
46 double range;
47};
48
49/*
50 * Create a new empty histogram
51 */
52
53irplib_hist *
54irplib_hist_new(void)
55{
56 return (irplib_hist *) cpl_calloc(1, sizeof(irplib_hist));
57}
58
59/*
60 * Delete a histogram
61 */
62
63void
64irplib_hist_delete(irplib_hist * d)
65{
66 if (d == NULL)
67 return;
68
69 if (d -> bins)
70 cpl_free(d -> bins);
71
72 cpl_free(d);
73}
74
75/*
76 * Initialise a histogram with user-defined values
77 */
78
79cpl_error_code
80irplib_hist_init(irplib_hist * hist,
81 unsigned long nbins,
82 double start,
83 double range)
84{
85 /* Test the entries */
86 cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
87 cpl_ensure_code(nbins > 0, CPL_ERROR_ILLEGAL_INPUT);
88 cpl_ensure_code(range > 0, CPL_ERROR_ILLEGAL_INPUT);
89 cpl_ensure_code(hist -> bins == NULL, CPL_ERROR_ILLEGAL_INPUT);
90
91 /* Initialise the histogram structure */
92 hist -> bins = (unsigned long *) cpl_calloc(nbins, sizeof(unsigned long));
93 hist -> nbins = nbins;
94 hist -> start = start;
95 hist -> range = range;
96
97 return cpl_error_get_code();
98}
99
100/*
101 * Return the value of a histogram bin.
102 * An uninitialised histogram is considered an illegal input.
103 */
104
105unsigned long
106irplib_hist_get_value(const irplib_hist * hist,
107 const unsigned long binpos)
108{
109 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
110 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
111 cpl_ensure(binpos < hist -> nbins, CPL_ERROR_ILLEGAL_INPUT, 0);
112
113 return hist -> bins[binpos];
114}
115
116/*
117 * Return the number of bins in the histogram.
118 */
119
120unsigned long
121irplib_hist_get_nbins(const irplib_hist * hist)
122{
123 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
124
125 return hist -> nbins;
126}
127
128/*
129 * Return the binwidth of the histogram.
130 */
131
132double
133irplib_hist_get_bin_size(const irplib_hist * hist)
134{
135 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
136 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
137
138 return hist -> range / (double)(hist -> nbins - 2);
139}
140
141/*
142 * Return the range covered by the histogram.
143 */
144
145double
146irplib_hist_get_range(const irplib_hist * hist)
147{
148 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
149
150 return hist -> range;
151}
152
153/*
154 * Return the real value corresponding
155 * to the inferior limit of the histogram..
156 */
157
158double
159irplib_hist_get_start(const irplib_hist * hist)
160{
161 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
162 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
163
164 return hist -> start;
165}
166
167/*
168 * Fill a histogram for an image.
169 * If the histogram is uninitialised,
170 * the function initialises it with default values.
171 */
172
173cpl_error_code
174irplib_hist_fill(irplib_hist * hist,
175 const cpl_image * image)
176{
177 double binwidth = 1.0;
178 int nsamples;
179 int i;
180 const float * data = 0;
181 const cpl_binary* bpm_data = 0;
182 const cpl_mask* bpm = 0;
183
184 /* Test the entries */
185 cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
186 cpl_ensure_code(image != NULL, CPL_ERROR_NULL_INPUT);
187
188 if (hist -> bins == NULL) {
189 const double hstart = cpl_image_get_min(image);
190 const double hrange = cpl_image_get_max(image) - hstart;
191 cpl_error_code error;
192
193 /*
194 * Whichever function that computes an optimal binwidth
195 * should be introduced inside this if-statement, here.
196 */
197
198 /* 2 extra-bins for possible out-of-range values */
199 const unsigned long nbins = (unsigned long) (hrange / binwidth) + 2;
200
201 error = irplib_hist_init(hist, nbins, hstart, hrange);
202 cpl_ensure_code(!error, error);
203 } else {
204 cpl_ensure_code(hist -> range > 0, CPL_ERROR_ILLEGAL_INPUT);
205
206 /* 2 bins reserved for possible out-of-range values */
207 binwidth = hist -> range / (double)(hist -> nbins - 2);
208 }
209
210 nsamples = cpl_image_get_size_x(image) * cpl_image_get_size_y(image);
211 data = cpl_image_get_data_float_const(image);
212 bpm = cpl_image_get_bpm_const(image);
213 if (bpm)
214 {
215 bpm_data = cpl_mask_get_data_const(bpm); // bad pixel mask
216 }
217
218 for (i = 0; i < nsamples; i++)
219 {
220 int pos = 0;
221 if(bpm_data && bpm_data[i] != CPL_BINARY_0)
222 {
223 continue;
224 }
225 pos = (int)((data[i] - hist -> start) / binwidth);
226 if (pos < 0)
227 {
228 hist -> bins[0]++;
229 } else if ((unsigned long) pos >= (hist -> nbins - 2))
230 {
231 hist -> bins[hist -> nbins - 1]++;
232 } else
233 {
234 hist -> bins[pos + 1]++;
235 }
236 }
237
238 return cpl_error_get_code();
239}
240
241/*
242 * Compute the maximum of a histogram.
243 * Return: the maximum value.
244 * The parameter max_where is a pointer to the position
245 * of the maximum in the histogram.
246 */
247
248unsigned long
249irplib_hist_get_max(const irplib_hist * hist,
250 unsigned long * maxpos)
251{
252 unsigned long max = 0;
253 unsigned long ui;
254
255 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
256 cpl_ensure(maxpos != NULL, CPL_ERROR_NULL_INPUT, 0);
257 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
258
259 for(ui = 0; ui < hist -> nbins; ui++) {
260 double c_value = irplib_hist_get_value(hist, ui);
261 if(c_value > max) {
262 max = c_value;
263 *maxpos = ui;
264 }
265 }
266
267 return max;
268}
269
270/*
271 * Cast a histogram into a table with a single column named "HIST"
272 */
273
274cpl_table *
275irplib_hist_cast_table(const irplib_hist * hist)
276{
277 cpl_table * table;
278 cpl_error_code error;
279
280 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, NULL);
281 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
282
283 table = cpl_table_new(hist -> nbins);
284
285 error = cpl_table_new_column(table, "HIST", CPL_TYPE_INT);
286 cpl_ensure(!error, error, NULL);
287
288 error = cpl_table_copy_data_int(table, "HIST", (int *)(hist -> bins));
289 cpl_ensure(!error, error, NULL);
290
291 return table;
292}
293
294/*
295 * Collapse the histogram: add the values of all bins.
296 * Used now only for debugging purposes.
297 */
298
299cpl_error_code
300irplib_hist_collapse(irplib_hist * hist,
301 unsigned long new_nbins)
302{
303 unsigned long ui, nuj;
304 unsigned long * old_bins;
305 unsigned long old_nbins;
306 double collapse_rate;
307 cpl_error_code error;
308 unsigned long rest;
309
310 cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
311 cpl_ensure_code(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT);
312 cpl_ensure_code(new_nbins > 0, CPL_ERROR_ILLEGAL_INPUT);
313 cpl_ensure_code(new_nbins <= hist -> nbins, CPL_ERROR_ILLEGAL_INPUT);
314
315 old_bins = hist -> bins;
316 old_nbins = hist -> nbins;
317
318 hist -> bins = NULL;
319 error = irplib_hist_init(hist, new_nbins, hist -> start, hist -> range);
320 cpl_ensure_code(!error, error);
321
322 collapse_rate = (double) (old_nbins - 2) / (double) (new_nbins - 2);
323
324 /* The out-of-range values are not affected by the collapsing operation */
325 hist -> bins[0] = old_bins[0];
326 hist -> bins[new_nbins - 1] = old_bins[old_nbins - 1];
327
328 rest = 0;
329 nuj = 1;
330
331 for (ui = 1; ui < new_nbins - 1; ui++) {
332 unsigned long uj;
333 const double up = collapse_rate * ui;
334
335 hist -> bins[ui] += rest;
336
337 for (uj = nuj; uj < (unsigned long) up + 1; uj++)
338 hist -> bins[ui] += old_bins[uj];
339
340 rest = (unsigned long)(up - (unsigned long) up) * old_bins[uj];
341 hist -> bins[ui] += rest;
342
343 rest = old_bins[uj] - rest;
344 nuj = uj + 1;
345 }
346
347 cpl_free(old_bins);
348
349 return cpl_error_get_code();
350}