add histogram equalization

This commit is contained in:
eddyem 2019-04-01 13:45:01 +03:00
parent 52679fe638
commit 89f8885276
11 changed files with 530 additions and 141 deletions

View File

@ -51,6 +51,36 @@ void FITS_reporterr(int *errcode){
*errcode = 0;
}
/**
* Functions to make intensity transforms of different kinds
* Carefully! All they valid only @[0,1]!!!
*/
static double lintrans(double in){
return in;
}
static double logtrans(double in){ // logaryphmic
return log(1. + in);
}
double exptrans(double in){ // exponential
return exp(in - 1.);
}
double powtrans(double in){ // x^2
return in*in;
}
double sqrtrans(double in){ // square root
return sqrt(in);
}
typedef double (*transfunct)(double in);
static transfunct tfunctions[TRANSF_COUNT] = {
[TRANSF_EXP] = exptrans,
[TRANSF_HISTEQ] = NULL, // another type of transform!
[TRANSF_LOG] = logtrans,
[TRANSF_LINEAR] = lintrans,
[TRANSF_POW] = powtrans,
[TRANSF_SQR] = sqrtrans
};
/**
* @brief mktransform - make image intensity transformation
* @param dimg (io) - double image
@ -60,7 +90,7 @@ void FITS_reporterr(int *errcode){
* Be carefull: image should be equalized before some types of transform
*/
doubleimage *mktransform(doubleimage *im, imgstat *st, intens_transform transf){
if(!im || !im->data || !st) return NULL;
if(!im || !im->data || !st || transf <= TRANSF_WRONG || transf >= TRANSF_COUNT) return NULL;
double max = st->max, min = st->min;
if((max-min) < 2.*DBL_EPSILON){
WARNX(_("Data range is too small"));
@ -69,34 +99,8 @@ doubleimage *mktransform(doubleimage *im, imgstat *st, intens_transform transf){
double *dimg = im->data;
if(transf == TRANSF_LINEAR) return im; // identity
if(transf == TRANSF_HISTEQ) return NULL; // histogram equalization; TODO: add this option too!
double (*transfn)(double in);
double logtrans(double in){ // logaryphmic
return log(1. + in);
}
double exptrans(double in){ // exponential
return exp(in);
}
double powtrans(double in){ // x^2
return in*in;
}
double sqrtrans(double in){ // square root
return sqrt(in);
}
switch(transf){
case TRANSF_EXP:
transfn = exptrans;
break;
case TRANSF_LOG:
transfn = logtrans;
break;
case TRANSF_POW:
transfn = powtrans;
break;
case TRANSF_SQR:
transfn = sqrtrans;
break;
default: return NULL;
}
double (*transfn)(double in) = tfunctions[transf];
if(!transfn) ERRX(_("Given transform type not supported yet"));
size_t totpix = im->totpix;
OMP_FOR()
for(size_t i = 0; i < totpix; ++i){
@ -115,14 +119,107 @@ static void palette_gray(double gray, uint8_t *rgb){
rgb[0] = rgb[1] = rgb[2] = (uint8_t)(255.*gray);
}
/**
* @brief palette_BR - palette from blue to red
* @param gray - nornmalized double value
* @param rgb - red, green and blue components
*/
// palette from black through red&yellow to white
static void palette_hot(double gray, uint8_t *rgb){
int i = (int)(gray * 3.);
double x = 3.*gray - (double)i;
uint8_t r = 255, g = 255, b = 255;
switch(i){
case 0:
r = (uint8_t)(255. * x);
g = 0;
b = 0;
break;
case 1:
g = (uint8_t)(255. * x);
b = 0;
break;
case 2:
b = (uint8_t)(255. * x);
break;
}
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}
// another palette from black through blue&cyan to white
static void palette_cold(double gray, uint8_t *rgb){
int i = (int)(gray * 3.);
double x = 3.*gray - (double)i;
uint8_t r = 255, g = 255, b = 255;
switch(i){
case 0:
r = 0;
g = 0;
b = (uint8_t)(255. * x);
break;
case 1:
g = (uint8_t)(255. * x);
r = 0;
break;
case 2:
r = (uint8_t)(255. * x);
break;
}
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}
// black->white->blue
static void palette_jet(double gray, uint8_t *rgb){
int i = (int)(gray * 8.);
double x = 8.*gray - (double)i;
uint8_t r = 0, g = 0, b = 127;
switch(i){
case 0:
r = 128 + (uint8_t)(127. * x);
g = 0;
b = 0;
break;
case 1:
r = 255;
g = (uint8_t)(128. * x);
b = 0;
break;
case 2:
r = 255;
g = 128 + (uint8_t)(127. * x);
b = 0;
break;
case 3:
r = 255 - (uint8_t)(128. * x);
g = 255;
b = (uint8_t)(128. * x);
break;
case 4:
r = 127 - (uint8_t)(127. * x);
g = 255;
b = 128 + (uint8_t)(127. * x);
break;
case 5:
r = 0;
g = 255 - (uint8_t)(128. * x);
b = 255;
break;
case 6:
r = 0;
g = 127 - (uint8_t)(127. * x);
b = 255;
break;
case 7:
r = 0;
g = 0;
b = 255 - (uint8_t)(128. * x);
break;
}
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}
// blue->red->yellow->white
static void palette_BR(double gray, uint8_t *rgb){
int i = (int)(gray * 4.);
double x = gray - (double)i * .25;
double x = 4.*gray - (double)i;
uint8_t r = 0, g = 0, b = 0;
switch(i){
case 0:
@ -152,7 +249,10 @@ static void palette_BR(double gray, uint8_t *rgb){
typedef void (*palette)(double, uint8_t[3]); // pointer to palette function
static palette palette_F[PALETTE_COUNT] = {
[PALETTE_GRAY] = palette_gray,
[PALETTE_BR] = palette_BR
[PALETTE_BR] = palette_BR,
[PALETTE_HOT] = palette_hot,
[PALETTE_COLD] = palette_cold,
[PALETTE_JET] = palette_jet
};
/**
@ -162,8 +262,9 @@ static palette palette_F[PALETTE_COUNT] = {
* @return allocated here array with color image
*/
uint8_t *convert2palette(doubleimage *im, image_palette cmap){
if(!im || !im->data || cmap < 0 || cmap >= PALETTE_COUNT) return NULL;
if(!im || !im->data || cmap <= PALETTE_WRONG || cmap >= PALETTE_COUNT) return NULL;
palette impalette = palette_F[cmap];
if(impalette == NULL) ERRX(_("Given colormap doesn't support yet"));
size_t totpix = im->totpix;
if(totpix == 0) return NULL;
double *inarr = im->data;

View File

@ -126,14 +126,19 @@ typedef enum{
TRANSF_EXP,
TRANSF_POW,
TRANSF_SQR,
TRANSF_HISTEQ
TRANSF_HISTEQ,
TRANSF_COUNT // amount of transforms
} intens_transform;
// different color maps
typedef enum{
PALETTE_GRAY = 0,
PALETTE_WRONG = 0,
PALETTE_GRAY,
PALETTE_BR,
PALETTE_COUNT
PALETTE_HOT,
PALETTE_COLD,
PALETTE_JET,
PALETTE_COUNT // amount of palettes
} image_palette;
typedef union{
@ -158,6 +163,13 @@ typedef struct{
FITSHDU *curHDU; // pointer to current HDU
} FITS;
typedef struct{
size_t *data; // histogram data
size_t size; // amount of levels
size_t totpix; // total amount of pixels
double *levels; // levels (for histograms of double images) for each H value
}histogram;
/**************************************************************************************
* fitskeywords.c *
**************************************************************************************/
@ -223,6 +235,14 @@ void initomp();
doubleimage *mktransform(doubleimage *im, imgstat *st, intens_transform transf);
uint8_t *convert2palette(doubleimage *im, image_palette cmap);
/**************************************************************************************
* histogram.c *
**************************************************************************************/
void histogram_free(histogram **H);
histogram *dbl2histogram(doubleimage *im, size_t nvalues);
doubleimage *dbl_histcutoff(doubleimage *im, size_t nlevls, double fracbtm, double fractop);
doubleimage *dbl_histeq(doubleimage *im, size_t nlevls);
/*
// pointer to image conversion function
typedef FITS* (*imfuncptr)(FITS *in, Filter *f, Itmarray *i);

View File

@ -21,7 +21,8 @@
/*
* Read FITS image, convert it to double and save as JPEG
* with given pallette.
* with given pallette. Also make simplest intensity (including histogram)
* transformations.
* WARNING! Supports only 2-dimensional images
*/
@ -33,6 +34,7 @@ typedef struct{
char *palette; // palette to convert FITS image
int nhdu; // HDU number to read image from
int rewrite; // rewrite output file
int nlvl; // amount of histogram levels
} glob_pars;
/*
@ -41,6 +43,7 @@ typedef struct{
static int help;
static glob_pars G = {
.nhdu = 1,
.nlvl = 100
};
/*
@ -53,10 +56,11 @@ static myoption cmdlnopts[] = {
{"inname", NEED_ARG, NULL, 'i', arg_string, APTR(&G.fitsname), _("name of input file")},
{"outpname",NEED_ARG, NULL, 'o', arg_string, APTR(&G.outfile), _("output file name (jpeg)")},
{"textline",NEED_ARG, NULL, 't', arg_string, APTR(&G.text), _("add text line to output image (at bottom)")},
{"palette", NEED_ARG, NULL, 'p', arg_string, APTR(&G.palette), _("convert as given palette")},
{"palette", NEED_ARG, NULL, 'p', arg_string, APTR(&G.palette), _("convert as given palette (linear, br, hot)")},
{"hdunumber",NEED_ARG, NULL, 'n', arg_int, APTR(&G.nhdu), _("open image from given HDU number")},
{"transform",NEED_ARG, NULL, 'T', arg_string, APTR(&G.transform), _("type of intensity transformation (log, sqr, exp, pow)")},
{"rewrite", NO_ARGS, NULL, 'r', arg_none, APTR(&G.rewrite), _("rewrite output file")},
{"histlvl", NEED_ARG, NULL, 'l', arg_int, APTR(&G.nlvl), _("amount of levels for histogram calculation")},
end_option
};
@ -121,26 +125,6 @@ static bool write_jpeg(const char *fname, const uint8_t *data, const char *str,
return TRUE;
}
/**
* @brief conv2rgb - convert grayscale normalized image to grayscale RGB
* @param inarr (i) - input array
* @param totpix - its size
* @return allocated here array with data
*
static uint8_t *conv2rgb(doubleimage *in){
if(!in) return NULL;
size_t totpix = in->totpix;
if(totpix == 0) return NULL;
double *inarr = in->data;
uint8_t *colored = MALLOC(uint8_t, totpix * 3);
OMP_FOR()
for(size_t i = 0; i < totpix; ++i){
uint8_t *pcl = &colored[i*3];
pcl[0] = pcl[1] = pcl[2] = (uint8_t)(inarr[i] * 255.);
}
return colored;
}*/
/**
* @brief gettransf - convert string with transformation type into intens_transform
* @param transf - type of transformation
@ -183,31 +167,65 @@ static intens_transform gettransf(const char *transf){
/**
* @brief palette_transform - transform string with colormap name into its number
* @param p - colormap name
* @return PALETTE_COUNT if wrong or appropriate palette
* @return PALETTE_WRONG if wrong or appropriate palette
*/
static image_palette palette_transform(char *p){
if(!p) return PALETTE_COUNT;
if(!p) return PALETTE_WRONG;
switch(p[0]){
case 'B':
case 'b':
return PALETTE_BR;
break;
case 'c':
case 'C':
return PALETTE_COLD;
break;
case 'g':
case 'G':
return PALETTE_GRAY;
break;
case 'h':
case 'H':
return PALETTE_HOT;
break;
case 'j':
case 'J':
return PALETTE_JET;
break;
default:
return PALETTE_COUNT;
return PALETTE_WRONG;
}
}
void print_histo(histogram *H){
if(!H) return;
size_t *histo = H->data;
double *lvls = H->levels;
green("Histogram:\n");
for(size_t i = 0; i < H->size; ++i){
if(histo[i] == 0) continue;
printf("%5zd [%3zd%%]: %zd (%g..%g)\n", i, (100*histo[i])/H->totpix, histo[i], lvls[i], lvls[i+1]);
}
printf("\n");
}
int main(int argc, char *argv[]){
intens_transform tr = TRANSF_LINEAR;
initial_setup();
parse_args(argc, argv);
if(!G.fitsname) ERRX(_("No input filename given!"));
if(!G.outfile) ERRX(_("Point the name of output file!"));
intens_transform tr = TRANSF_LINEAR;
if(G.transform) tr = gettransf(G.transform);
if(tr == TRANSF_WRONG) ERRX(_("Wrong transform: %s"), G.transform);
if(!file_absent(G.outfile) && !G.rewrite) ERRX(_("File %s exists"), G.outfile);
image_palette colormap = PALETTE_GRAY;
if(G.palette){ // convert normalized image due to choosen palette
colormap = palette_transform(G.palette);
if(colormap == PALETTE_WRONG) ERRX(_("Wrong colormap name"));
}
DBG("Open file %s", G.fitsname);
FITS *f = FITS_read(G.fitsname);
if(!f) ERRX(_("Failed to open"));
DBG("HERE");
green("got file %s, HDUs: %d, working HDU #%d\n", G.fitsname, f->NHDUs, G.nhdu);
if(f->NHDUs < G.nhdu) ERRX(_("File %s consists %d HDUs!"), G.fitsname, f->NHDUs);
@ -231,12 +249,9 @@ int main(int argc, char *argv[]){
st = get_imgstat(dblimg, NULL);
#endif
DBG("After transformation: MIN=%g, MAX=%g, AVR=%g, STD=%g", st->min, st->max, st->mean, st->std);
image_palette colormap = PALETTE_GRAY;
if(G.palette){ // convert normalized image due to choosen palette
colormap = palette_transform(G.palette);
if(colormap == PALETTE_COUNT) ERRX(_("Wrong colormap name"));
}
//uint8_t *colored = conv2rgb(dblimg);
histogram *h = dbl2histogram(dblimg, G.nlvl);
print_histo(h);
histogram_free(&h);
uint8_t *colored = convert2palette(dblimg, colormap);
DBG("Save jpeg to %s", G.outfile);
if(!write_jpeg(G.outfile, colored, G.text, img)) ERRX(_("Can't save modified file %s"), G.outfile);

View File

@ -1,11 +1,10 @@
/*
* fits.c - cfitsio routines
* This file is part of the FITSmaniplib project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>, <eddy@sao.ru>.
*
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@ -14,10 +13,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FITSmanip.h"
#include "local.h"

View File

@ -1,11 +1,10 @@
/*
* fits.c - cfitsio routines
* This file is part of the FITSmaniplib project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>, <eddy@sao.ru>.
*
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@ -14,10 +13,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FITSmanip.h"
#include "local.h"
@ -324,6 +322,11 @@ void dblima_free(doubleimage **im){
FREE(*im);
}
static double ubyteconv(const void *data){return (double)*((const uint8_t*)data);}
static double ushortconv(const void *data){return (double)*((const uint16_t*)data);}
static double ulongconv(const void *data){return (double)*((const uint32_t*)data);}
static double ulonglongconv(const void *data){return (double)*((const uint64_t*)data);}
static double floatconv(const void *data){return (double)*((const float*)data);}
/**
* @brief image2double convert image values to double
* @param img - input image
@ -338,12 +341,7 @@ doubleimage *image2double(FITSimage *img){
dblim->height = img->naxes[1];
dblim->totpix = tot;
DBG("image: %ldx%ld=%ld", dblim->width, dblim->height, tot);
double (*fconv)(uint8_t *x);
double ubyteconv(uint8_t *data){return (double)*data;}
double ushortconv(uint8_t *data){return (double)*((uint16_t*)data);}
double ulongconv(uint8_t *data){return (double)*((uint32_t*)data);}
double ulonglongconv(uint8_t *data){return (double)*((uint64_t*)data);}
double floatconv(uint8_t *data){return (double)*((float*)data);}
double (*fconv)(const void *x);
switch(img->dtype){
case TBYTE:
fconv = ubyteconv;

View File

@ -1,11 +1,10 @@
/*
* fits.c - cfitsio routines
* This file is part of the FITSmaniplib project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>, <eddy@sao.ru>.
*
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@ -14,10 +13,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FITSmanip.h"
#include "local.h"

View File

@ -1,11 +1,10 @@
/*
* fits.c - cfitsio routines
* This file is part of the FITSmaniplib project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>, <eddy@sao.ru>.
*
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@ -14,10 +13,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FITSmanip.h"
#include "local.h"

194
histogram.c Normal file
View File

@ -0,0 +1,194 @@
/*
* This file is part of the FITSmaniplib project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>, <eddy@sao.ru>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FITSmanip.h"
#include "local.h"
/**************************************************************************************
* Histogram routines *
**************************************************************************************/
void histogram_free(histogram **H){
if(!H || !*H) return;
FREE((*H)->levels);
FREE((*H)->data);
FREE(*H);
}
/**
* @brief dbl2histogram - calculate histogram of normalized image `im`
* @param im (i) - input image
* @param nvalues - amount of levels (more than 2, less than 65536)
* @return array with image histogram (allocated here)
*/
histogram *dbl2histogram(doubleimage *im, size_t nvalues){
if(!im || !im->data || nvalues < 2 || im->totpix < 1) return NULL;
if(nvalues > 65535){
WARNX(_("Amount of histogram levels should be less than 65536!"));
return NULL;
}
histogram *H = MALLOC(histogram, 1);
size_t *histo = MALLOC(size_t, nvalues);
double *lvls = MALLOC(double, nvalues+1); // have greatest value -> its size larger
H->data = histo;
H->levels = lvls;
H->size = nvalues;
H->totpix = im->totpix;
for(size_t i = 0; i < im->totpix; ++i){
size_t v = im->data[i] * nvalues;
if(v >= nvalues) v = nvalues-1;
++histo[v];
}
for(size_t i = 0; i <= nvalues; ++i)
lvls[i] = ((double)i) / ((double)nvalues);
return H;
}
/**
* @brief lininterp - linear interpolation
* @param bordx - borders by X-axis (xlow, xhigh)
* @param bordy - borders by Y-axis (ylow, yhigh)
* @param x - coordinate of x value
* @return
*
static double lininterp(const double bordx[2], const double bordy[2], double x){
return (bordx[0] + (x-bordx[0])*(bordy[1]-bordy[1])/(bordx[1]-bordx[0]));
}*/
/**
* @brief dbl_histcutoff - cutoff histogram of double image with uniform intensity recalculation
* @param im (io) - image
* @param nlevls - amount of levels (2..65535) of histogram
* @param fracbtm - fraction of deleted pixels from zero
* @param fractop - fraction of deleted pixels from top
* @return pointer to im (equalized) or NULL
* WARNING! Works only for normalized image!
*/
doubleimage *dbl_histcutoff(doubleimage *im, size_t nlevls, double fracbtm, double fractop){
if(!im || !im->data) return NULL;
double success = TRUE; // return OK, if true; NULL if false
if(fracbtm > 1. || fracbtm < 0.){
WARNX(_("Bottom fraction should be in [0, 1)"));
return NULL;
}
if(fractop > 1. || fractop < 0.){
WARNX(_("Top fraction should be in (0, 1]"));
return NULL;
}
histogram *hist = dbl2histogram(im, nlevls);
if(!hist || !hist->data || !hist->levels){
success = FALSE;
goto theret;
}
// prepare data for top & bottom throwing out
size_t Nbot = fracbtm * hist->totpix, Ntop = fractop * hist->totpix;
size_t Ncur = 0; // pixel counter
ssize_t botidx = -1, topidx = (ssize_t)nlevls; // botidx->0, topidx -> 1.
DBG("Nbot: %zd, Ntop: %zd, total: %zd", Nbot, Ntop, hist->totpix);
if(Nbot + Ntop >= hist->totpix){
WARNX(_("No pixels leave to process, have: %zd, need: %zd"), hist->totpix, Nbot + Ntop);
success = FALSE;
goto theret;
}
Ntop = hist->totpix - Ntop;
// search lower and upper limits
for(size_t i = 0; i < nlevls; ++i){
Ncur += hist->data[i];
DBG("i=%zd, Ncur=%zd", i, Ncur);
if(Ncur > Nbot && botidx == -1){
botidx = i; // found bottom index
if(Ntop == hist->totpix) break;
}else if(Ncur > Ntop){
topidx = i;
break;
}
}
if(botidx < 0){
WARNX(_("Can't find bottom index"));
success = FALSE;
goto theret;
}
// top and bottom values which will be new 0 & 1
double botval = hist->levels[botidx]; // lowest value -> 0.
double topval = hist->levels[topidx]; // highest value -> 1.
DBG("Bot: %zd, Top: %zd, botval: %g, topval: %g", botidx, topidx, botval, topval);
double range = topval - botval; // range -> 1.
DBG("botval=%g, topval=%g, range=%g", botval, topval, range);
// Now we should convert intensities according to new limits
// botidx -> 0., topidx -> 1.
OMP_FOR()
for(size_t i = 0; i < im->totpix; ++i){// index in old histogram
double xx = im->data[i];
if(xx < botval) xx = 0.;
else xx = (xx - botval) / range;
if(xx > 1.) xx = 1.;
im->data[i] = xx;
}
theret:
histogram_free(&hist);
if(success) return im;
else return NULL;
}
/**
* @brief dbl_histcutoff - modify image by histogram equalisation
* @param im - image to transform
* @param nlevls - levels amount (2..65535)
* @return
*/
doubleimage *dbl_histeq(doubleimage *im, size_t nlevls){
if(!im || !im->data) return NULL;
double success = TRUE;
histogram *hist = dbl2histogram(im, nlevls);
if(!hist || !hist->data || !hist->levels){
success = FALSE;
goto theret;
}
double *newlevels = MALLOC(double, nlevls+1);
size_t cumul = 0;
for(size_t i = 0; i < nlevls; ++i){
cumul += hist->data[i];
// calculate new gray level
newlevels[i+1] = ((double)cumul) / hist->totpix;
DBG("newlevels[%zd]=%g", i+1, newlevels[i+1]);
}
// now we can change image values due to new level
OMP_FOR()
for(size_t i = 0; i < im->totpix; ++i){
double d = im->data[i];
double dnl = d * nlevls;
size_t v = (size_t)dnl;
if(v >= nlevls){
v = nlevls-1;
}
double frac = dnl - v;
if(frac < 0.){
DBG("frac=%g<0", frac);
frac = 0.;
}else if(frac > 1.){
DBG("frac=%g>1", frac);
frac = 1;
}
im->data[i] = (newlevels[v+1] - newlevels[v]) * frac + newlevels[v];
}
FREE(newlevels);
theret:
histogram_free(&hist);
if(success) return im;
else return NULL;
}

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-29 21:12+0300\n"
"POT-Creation-Date: 2019-04-01 13:42+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,65 +17,99 @@ msgstr ""
"Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:119
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/FITSmanip.c:96
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:427
msgid "Data range is too small"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/FITSmanip.c:103
msgid "Given transform type not supported yet"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/FITSmanip.c:267
msgid "Given colormap doesn't support yet"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:117
msgid "Can't read HDU"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:147
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:145
msgid "Unknown HDU type"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:263
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:261
#, c-format
msgid "Can't get real path for %s, use cfitsio to rewrite"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:316
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:315
#, c-format
msgid "Found %d pixels with undefined value"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:357
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:366
msgid "Undefined image type, cant convert to double"
msgstr ""
#. / "îÅ ÍÏÇÕ ÓËÏÐÉÒÏ×ÁÔØ ÄÁÎÎÙÅ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:83
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:81
msgid "Can't copy data"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:132
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:130
msgid "Can't get value & comment"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:361
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:359
msgid "No keywords in given HDU"
msgstr ""
#. / "îÅ ÍÏÇÕ ÄÏÂÁ×ÉÔØ ÚÁÐÉÓØ × ÓÐÉÓÏË"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:377
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:375
msgid "Can't add record to list"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:121
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:119
msgid "strdup() failed!"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:142
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:140
msgid "Can't read row number!"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:159
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:157
#, c-format
msgid "Can't read column %d!"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:450
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:448
#, c-format
msgid "Can't write table %s!"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:460
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:458
#, c-format
msgid "Can't write column %s!"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:42
msgid "Amount of histogram levels should be less than 65536!"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:86
msgid "Bottom fraction should be in [0, 1)"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:90
msgid "Top fraction should be in (0, 1]"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:104
#, c-format
msgid "No pixels leave to process, have: %zd, need: %zd"
msgstr ""
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:122
msgid "Can't find bottom index"
msgstr ""

View File

@ -7,7 +7,7 @@
msgid ""
msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-29 20:32+0300\n"
"POT-Creation-Date: 2019-04-01 11:58+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -16,69 +16,102 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:42
msgid "Amount of histogram levels should be less than 65536!"
msgstr "ëÏÌÉÞÅÓÔ×Ï ÕÒÏ×ÎÅÊ ÇÉÓÔÏÇÒÁÍÍÙ ÎÅ ÄÏÌÖÎÏ ÐÒÅ×ÙÛÁÔØ 65535!"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:86
msgid "Bottom fraction should be in [0, 1)"
msgstr "äÏÌÑ ÓÎÉÚÕ ÄÏÌÖÎÁ ÂÙÔØ × ÄÉÁÐÁÚÏÎÅ [0, 1)"
#. / "îÅ ÍÏÇÕ ÄÏÂÁ×ÉÔØ ÚÁÐÉÓØ × ÓÐÉÓÏË"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:377
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:375
msgid "Can't add record to list"
msgstr "îÅ ÍÏÇÕ ÄÏÂÁ×ÉÔØ ÚÁÐÉÓØ × ÓÐÉÓÏË"
#. / "îÅ ÍÏÇÕ ÓËÏÐÉÒÏ×ÁÔØ ÄÁÎÎÙÅ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:83
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:81
msgid "Can't copy data"
msgstr "îÅ ÍÏÇÕ ÓËÏÐÉÒÏ×ÁÔØ ÄÁÎÎÙÅ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:263
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:122
msgid "Can't find bottom index"
msgstr "îÅ ÍÏÇÕ ÎÁÊÔÉ ÎÉÖÎÉÊ ÉÎÄÅËÓ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:261
#, c-format
msgid "Can't get real path for %s, use cfitsio to rewrite"
msgstr "îÅ ÍÏÇÕ ÏÐÒÅÄÅÌÉÔØ ÐÕÔØ (realpath) Ë %s, ÉÓÐÏÌØÚÕÀ cfitsio ÄÌÑ "
"ÐÅÒÅÚÁÐÉÓÉ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:132
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:130
#, fuzzy
msgid "Can't get value & comment"
msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ ÅÄÉÎÉÃÙ ÉÚÍÅÒÅÎÉÑ ÄÁÎÎÙÈ ÔÁÂÌÉÃÙ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:119
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:117
msgid "Can't read HDU"
msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ HDU"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:159
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:157
#, c-format
msgid "Can't read column %d!"
msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ ÓÔÏÌÂÅà %d!"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:142
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:140
#, fuzzy
msgid "Can't read row number!"
msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ ÓÔÏÌÂÅà %d!"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:460
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:458
#, c-format
msgid "Can't write column %s!"
msgstr "îÅ ÍÏÇÕ ÚÁÐÉÓÁÔØ ÓÔÏÌÂÅà %s!"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:450
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:448
#, c-format
msgid "Can't write table %s!"
msgstr "îÅ ÍÏÇÕ ÚÁÐÉÓÁÔØ ÔÁÂÌÉÃÕ %s!"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:316
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/FITSmanip.c:96
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:427
msgid "Data range is too small"
msgstr "äÉÁÐÁÚÏÎ ÄÁÎÎÙÈ ÓÌÉÛËÏÍ ÍÁÌ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:315
#, c-format
msgid "Found %d pixels with undefined value"
msgstr "îÁÊÄÅÎÏ %d ÐÉËÓÅÌÅÊ Ó ÎÅÏÐÒÅÄÅÌÅÎÎÙÍÉ ÚÎÁÞÅÎÉÑÍÉ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:361
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/FITSmanip.c:267
msgid "Given colormap doesn't support yet"
msgstr "äÁÎÎÁÑ ÐÁÌÉÔÒÁ ÐÏËÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/FITSmanip.c:103
msgid "Given transform type not supported yet"
msgstr "äÁÎÎÙÊ ÔÉÐ ÐÒÅÏÂÒÁÚÏ×ÁÎÉÊ ÐÏËÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitskeywords.c:359
msgid "No keywords in given HDU"
msgstr "÷ ÄÁÎÎÏÍ HDU ËÌÀÞÉ ÏÔÓÕÔÓÔ×ÕÀÔ"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:357
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:104
#, c-format
msgid "No pixels leave to process, have: %zd, need: %zd"
msgstr "îÅ ÏÓÔÁÌÏÓØ ÐÉËÓÅÌÅÊ ÄÌÑ ÏÂÒÁÂÏÔËÉ, ÅÓÔØ: %zd, ÔÒÅÂÕÅÔÓÑ: %zd"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/histogram.c:90
msgid "Top fraction should be in (0, 1]"
msgstr "÷ÅÒÈÎÑÑ ÄÏÌÑ ÄÏÌÖÎÁ ÂÙÔØ × ÄÉÁÐÁÚÏÎÅ (0, 1]"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsimages.c:366
msgid "Undefined image type, cant convert to double"
msgstr "îÅÏÐÒÅÄÅÌÅÎÎÙÊ ÔÉÐ ÆÁÊÌÁ, ÎÅ ÍÏÇÕ ÐÒÅÏÂÒÁÚÏ×ÁÔØ × double"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:147
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitsfiles.c:145
msgid "Unknown HDU type"
msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÔÉÐ HDU"
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:121
#: /home/eddy/C-files/FITSmaniplib/sharedlib_template/fitstables.c:119
msgid "strdup() failed!"
msgstr "îÅ ÕÄÁÌÏÓØ ÓÄÅÌÁÔØ strdup()!"