00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036
00037 #include <math.h>
00038
00039 #include "irplib_hist.h"
00040
00041 struct _irplib_hist_
00042 {
00043 unsigned long * bins;
00044 unsigned long nbins;
00045 double start;
00046 double range;
00047 };
00048
00049
00050
00051
00052
00053 irplib_hist *
00054 irplib_hist_new(void)
00055 {
00056 return (irplib_hist *) cpl_calloc(1, sizeof(irplib_hist));
00057 }
00058
00059
00060
00061
00062
00063 void
00064 irplib_hist_delete(irplib_hist * d)
00065 {
00066 if (d == NULL)
00067 return;
00068
00069 if (d -> bins)
00070 cpl_free(d -> bins);
00071
00072 cpl_free(d);
00073 }
00074
00075
00076
00077
00078
00079 cpl_error_code
00080 irplib_hist_init(irplib_hist * hist,
00081 unsigned long nbins,
00082 double start,
00083 double range)
00084 {
00085
00086 cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
00087 cpl_ensure_code(nbins > 0, CPL_ERROR_ILLEGAL_INPUT);
00088 cpl_ensure_code(range > 0, CPL_ERROR_ILLEGAL_INPUT);
00089 cpl_ensure_code(hist -> bins == NULL, CPL_ERROR_ILLEGAL_INPUT);
00090
00091
00092 hist -> bins = (unsigned long *) cpl_calloc(nbins, sizeof(unsigned long));
00093 hist -> nbins = nbins;
00094 hist -> start = start;
00095 hist -> range = range;
00096
00097 return cpl_error_get_code();
00098 }
00099
00100
00101
00102
00103
00104
00105 unsigned long
00106 irplib_hist_get_value(const irplib_hist * hist,
00107 const unsigned long binpos)
00108 {
00109 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00110 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
00111 cpl_ensure(binpos < hist -> nbins, CPL_ERROR_ILLEGAL_INPUT, 0);
00112
00113 return hist -> bins[binpos];
00114 }
00115
00116
00117
00118
00119
00120 unsigned long
00121 irplib_hist_get_nbins(const irplib_hist * hist)
00122 {
00123 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00124
00125 return hist -> nbins;
00126 }
00127
00128
00129
00130
00131
00132 double
00133 irplib_hist_get_bin_size(const irplib_hist * hist)
00134 {
00135 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00136 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
00137
00138 return hist -> range / (double)(hist -> nbins - 2);
00139 }
00140
00141
00142
00143
00144
00145 double
00146 irplib_hist_get_range(const irplib_hist * hist)
00147 {
00148 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00149
00150 return hist -> range;
00151 }
00152
00153
00154
00155
00156
00157
00158 double
00159 irplib_hist_get_start(const irplib_hist * hist)
00160 {
00161 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00162 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
00163
00164 return hist -> start;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 cpl_error_code
00174 irplib_hist_fill(irplib_hist * hist,
00175 const cpl_image * image)
00176 {
00177 double binwidth = 1.0;
00178 int nsamples;
00179 int i;
00180 const float * data = 0;
00181 const cpl_binary* bpm_data = 0;
00182 const cpl_mask* bpm = 0;
00183 cpl_error_code error;
00184
00185
00186 cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
00187 cpl_ensure_code(image != NULL, CPL_ERROR_NULL_INPUT);
00188
00189 if (hist -> bins == NULL) {
00190 const double hstart = cpl_image_get_min(image);
00191 const double hrange = cpl_image_get_max(image) - hstart;
00192
00193
00194
00195
00196
00197
00198
00199 const unsigned long nbins = (unsigned long) (hrange / binwidth) + 2;
00200
00201 error = irplib_hist_init(hist, nbins, hstart, hrange);
00202 cpl_ensure_code(!error, error);
00203 } else {
00204 cpl_ensure_code(hist -> range > 0, CPL_ERROR_ILLEGAL_INPUT);
00205
00206
00207 binwidth = hist -> range / (double)(hist -> nbins - 2);
00208 }
00209
00210 nsamples = cpl_image_get_size_x(image) * cpl_image_get_size_y(image);
00211 data = cpl_image_get_data_float_const(image);
00212 bpm = cpl_image_get_bpm_const(image);
00213 if (bpm)
00214 {
00215 bpm_data = cpl_mask_get_data_const(bpm);
00216 }
00217
00218 for (i = 0; i < nsamples; i++)
00219 {
00220 int pos = 0;
00221 if(bpm_data && bpm_data[i] == CPL_BINARY_1)
00222 {
00223 continue;
00224 }
00225 pos = (int)((data[i] - hist -> start) / binwidth);
00226 if (pos < 0)
00227 {
00228 hist -> bins[0]++;
00229 } else if ((unsigned long) pos >= (hist -> nbins - 2))
00230 {
00231 hist -> bins[hist -> nbins - 1]++;
00232 } else
00233 {
00234 hist -> bins[pos + 1]++;
00235 }
00236 }
00237
00238 return cpl_error_get_code();
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 unsigned long
00249 irplib_hist_get_max(const irplib_hist * hist,
00250 unsigned long * maxpos)
00251 {
00252 unsigned long max = 0;
00253 unsigned long ui;
00254
00255 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, 0);
00256 cpl_ensure(maxpos != NULL, CPL_ERROR_NULL_INPUT, 0);
00257 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, 0);
00258
00259 for(ui = 0; ui < hist -> nbins; ui++) {
00260 double c_value = irplib_hist_get_value(hist, ui);
00261 if(c_value > max) {
00262 max = c_value;
00263 *maxpos = ui;
00264 }
00265 }
00266
00267 return max;
00268 }
00269
00270
00271
00272
00273
00274 cpl_table *
00275 irplib_hist_cast_table(const irplib_hist * hist)
00276 {
00277 cpl_table * table;
00278 cpl_error_code error;
00279
00280 cpl_ensure(hist != NULL, CPL_ERROR_NULL_INPUT, NULL);
00281 cpl_ensure(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00282
00283 table = cpl_table_new(hist -> nbins);
00284
00285 error = cpl_table_new_column(table, "HIST", CPL_TYPE_INT);
00286 cpl_ensure(!error, error, NULL);
00287
00288 error = cpl_table_copy_data_int(table, "HIST", (int *)(hist -> bins));
00289 cpl_ensure(!error, error, NULL);
00290
00291 return table;
00292 }
00293
00294
00295
00296
00297
00298
00299 cpl_error_code
00300 irplib_hist_collapse(irplib_hist * hist,
00301 unsigned long new_nbins)
00302 {
00303 unsigned long ui, nuj;
00304 unsigned long * old_bins;
00305 unsigned long old_nbins;
00306 double collapse_rate;
00307 cpl_error_code error;
00308 unsigned long rest;
00309
00310 cpl_ensure_code(hist != NULL, CPL_ERROR_NULL_INPUT);
00311 cpl_ensure_code(hist -> bins != NULL, CPL_ERROR_ILLEGAL_INPUT);
00312 cpl_ensure_code(new_nbins > 0, CPL_ERROR_ILLEGAL_INPUT);
00313 cpl_ensure_code(new_nbins <= hist -> nbins, CPL_ERROR_ILLEGAL_INPUT);
00314
00315 old_bins = hist -> bins;
00316 old_nbins = hist -> nbins;
00317
00318 hist -> bins = NULL;
00319 error = irplib_hist_init(hist, new_nbins, hist -> start, hist -> range);
00320 cpl_ensure_code(!error, error);
00321
00322 collapse_rate = (double) (old_nbins - 2) / (double) (new_nbins - 2);
00323
00324
00325 hist -> bins[0] = old_bins[0];
00326 hist -> bins[new_nbins - 1] = old_bins[old_nbins - 1];
00327
00328 rest = 0;
00329 nuj = 1;
00330
00331 for (ui = 1; ui < new_nbins - 1; ui++) {
00332 unsigned long uj;
00333 const double up = collapse_rate * ui;
00334
00335 hist -> bins[ui] += rest;
00336
00337 for (uj = nuj; uj < (unsigned long) up + 1; uj++)
00338 hist -> bins[ui] += old_bins[uj];
00339
00340 rest = (unsigned long)(up - (unsigned long) up) * old_bins[uj];
00341 hist -> bins[ui] += rest;
00342
00343 rest = old_bins[uj] - rest;
00344 nuj = uj + 1;
00345 }
00346
00347 cpl_free(old_bins);
00348
00349 return cpl_error_get_code();
00350 }