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