00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <math.h>
00030 #include <limits.h>
00031 #include <string.h>
00032
00033
00034 #include "balance_lib.h"
00035
00043 static void minmax_u8(const unsigned char *data, size_t size,
00044 unsigned char *ptr_min, unsigned char *ptr_max)
00045 {
00046 unsigned char min, max;
00047 size_t i;
00048
00049
00050 min = data[0];
00051 max = data[0];
00052 for (i = 1; i < size; i++) {
00053 if (data[i] < min)
00054 min = data[i];
00055 if (data[i] > max)
00056 max = data[i];
00057 }
00058
00059
00060 if (NULL != ptr_min)
00061 *ptr_min = min;
00062 if (NULL != ptr_max)
00063 *ptr_max = max;
00064 return;
00065 }
00066
00074 static void minmax_f32(const float *data, size_t size,
00075 float *ptr_min, float *ptr_max)
00076 {
00077 float min, max;
00078 size_t i;
00079
00080
00081 min = data[0];
00082 max = data[0];
00083 for (i = 1; i < size; i++) {
00084 if (data[i] < min)
00085 min = data[i];
00086 if (data[i] > max)
00087 max = data[i];
00088 }
00089
00090
00091 if (NULL != ptr_min)
00092 *ptr_min = min;
00093 if (NULL != ptr_max)
00094 *ptr_max = max;
00095 return;
00096 }
00097
00111 static void quantiles_u8(const unsigned char *data, size_t size,
00112 size_t nb_min, size_t nb_max,
00113 unsigned char *ptr_min, unsigned char *ptr_max)
00114 {
00115
00116
00117
00118
00119 size_t h_size = UCHAR_MAX + 1;
00120 size_t histo[UCHAR_MAX + 1];
00121 size_t i;
00122
00123
00124 memset(histo, 0x00, h_size * sizeof(size_t));
00125 for (i = 0; i < size; i++)
00126 histo[(size_t) data[i]] += 1;
00127 for (i = 1; i < h_size; i++)
00128 histo[i] += histo[i - 1];
00129
00130
00131
00132 if (NULL != ptr_min) {
00133
00134
00135 i = 0;
00136 while (i < h_size && histo[i] <= nb_min)
00137 i++;
00138
00139 *ptr_min = (unsigned char) i;
00140 }
00141
00142 if (NULL != ptr_max) {
00143
00144
00145 i = h_size - 1;
00146
00147 while (i < h_size && histo[i] > (size - nb_max))
00148 i--;
00149
00150
00151
00152
00153
00154 if (i < h_size - 1)
00155 i++;
00156 *ptr_max = (unsigned char) i;
00157 }
00158 return;
00159 }
00160
00168 static int cmp_f32(const void *a, const void *b)
00169 {
00170 if (*(const int *) a > *(const int *) b)
00171 return 1;
00172 if (*(const int *) a < *(const int *) b)
00173 return -1;
00174 return 0;
00175 }
00176
00194 static void quantiles_f32(const float *data, size_t size,
00195 size_t nb_min, size_t nb_max,
00196 float *ptr_min, float *ptr_max)
00197 {
00198 float *data_tmp;
00199
00200 data_tmp = (float *) malloc(size * sizeof(float));
00201
00202
00203 memcpy(data_tmp, data, size * sizeof(float));
00204 qsort(data_tmp, size, sizeof(float), &cmp_f32);
00205
00206
00207 if (NULL != ptr_min)
00208 *ptr_min = data_tmp[nb_min];
00209 if (NULL != ptr_max)
00210 *ptr_max = data_tmp[size - 1 - nb_max];
00211
00212 free(data_tmp);
00213 return;
00214 }
00215
00228 static unsigned char *rescale_u8(unsigned char *data, size_t size,
00229 unsigned char min, unsigned char max)
00230 {
00231 size_t i;
00232
00233 if (max <= min)
00234 for (i = 0; i < size; i++)
00235 data[i] = UCHAR_MAX / 2;
00236 else {
00237
00238 unsigned char norm[UCHAR_MAX + 1];
00239 for (i = 0; i < min; i++)
00240 norm[i] = 0;
00241 for (i = min; i < max; i++)
00242
00243
00244
00245
00246
00247 norm[i] = (unsigned char) ((i - min) * UCHAR_MAX
00248 / (double) (max - min) + .5);
00249 for (i = max; i < UCHAR_MAX + 1; i++)
00250 norm[i] = UCHAR_MAX;
00251
00252 for (i = 0; i < size; i++)
00253 data[i] = norm[(size_t) data[i]];
00254 }
00255 return data;
00256 }
00257
00272 static float *rescale_f32(float *data, size_t size, float min, float max)
00273 {
00274 size_t i;
00275
00276 if (max <= min)
00277 for (i = 0; i < size; i++)
00278 data[i] = .5;
00279 else
00280 for (i = 0; i < size; i++)
00281 data[i] = (min > data[i] ? 0. :
00282 (max < data[i] ? 1. : (data[i] - min) / (max - min)));
00283
00284 return data;
00285 }
00286
00300 unsigned char *balance_u8(unsigned char *data, size_t size,
00301 size_t nb_min, size_t nb_max)
00302 {
00303 unsigned char min, max;
00304
00305
00306 if (NULL == data) {
00307 fprintf(stderr, "a pointer is NULL and should not be so\n");
00308 abort();
00309 }
00310 if (nb_min + nb_max >= size) {
00311 nb_min = (size - 1) / 2;
00312 nb_max = (size - 1) / 2;
00313 fprintf(stderr, "the number of pixels to flatten is too large\n");
00314 fprintf(stderr, "using (size - 1) / 2\n");
00315 }
00316
00317
00318 if (0 != nb_min || 0 != nb_max)
00319 quantiles_u8(data, size, nb_min, nb_max, &min, &max);
00320 else
00321 minmax_u8(data, size, &min, &max);
00322
00323
00324 (void) rescale_u8(data, size, min, max);
00325
00326 return data;
00327 }
00328
00342 float *balance_f32(float *data, size_t size, size_t nb_min, size_t nb_max)
00343 {
00344 float min, max;
00345
00346
00347 if (NULL == data) {
00348 fprintf(stderr, "a pointer is NULL and should not be so\n");
00349 abort();
00350 }
00351 if (nb_min + nb_max >= size) {
00352 nb_min = (size - 1) / 2;
00353 nb_max = (size - 1) / 2;
00354 fprintf(stderr, "the number of pixels to flatten is too large\n");
00355 fprintf(stderr, "using (size - 1) / 2\n");
00356 }
00357
00358
00359 if (0 != nb_min || 0 != nb_max)
00360 quantiles_f32(data, size, nb_min, nb_max, &min, &max);
00361 else
00362 minmax_f32(data, size, &min, &max);
00363
00364
00365 (void) rescale_f32(data, size, min, max);
00366
00367 return data;
00368 }