diff --git a/FITSmanip.c b/FITSmanip.c index 74dc2bd..dbbfa7e 100644 --- a/FITSmanip.c +++ b/FITSmanip.c @@ -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; diff --git a/FITSmanip.h b/FITSmanip.h index e46f060..8d467b4 100644 --- a/FITSmanip.h +++ b/FITSmanip.h @@ -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); diff --git a/examples/gd.c b/examples/gd.c index 3204fd4..c85be5a 100644 --- a/examples/gd.c +++ b/examples/gd.c @@ -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); diff --git a/fitsfiles.c b/fitsfiles.c index 0601cee..cf1870b 100644 --- a/fitsfiles.c +++ b/fitsfiles.c @@ -1,11 +1,10 @@ /* - * fits.c - cfitsio routines + * This file is part of the FITSmaniplib project. + * Copyright 2019 Edward V. Emelianov , . * - * Copyright 2015 Edward V. Emelianov - * - * 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 . */ + #include "FITSmanip.h" #include "local.h" diff --git a/fitsimages.c b/fitsimages.c index 8e1bc37..663d3b0 100644 --- a/fitsimages.c +++ b/fitsimages.c @@ -1,11 +1,10 @@ /* - * fits.c - cfitsio routines + * This file is part of the FITSmaniplib project. + * Copyright 2019 Edward V. Emelianov , . * - * Copyright 2015 Edward V. Emelianov - * - * 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 . */ + #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; diff --git a/fitskeywords.c b/fitskeywords.c index 8ae548d..220d464 100644 --- a/fitskeywords.c +++ b/fitskeywords.c @@ -1,11 +1,10 @@ /* - * fits.c - cfitsio routines + * This file is part of the FITSmaniplib project. + * Copyright 2019 Edward V. Emelianov , . * - * Copyright 2015 Edward V. Emelianov - * - * 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 . */ + #include "FITSmanip.h" #include "local.h" diff --git a/fitstables.c b/fitstables.c index e6c90aa..1a49762 100644 --- a/fitstables.c +++ b/fitstables.c @@ -1,11 +1,10 @@ /* - * fits.c - cfitsio routines + * This file is part of the FITSmaniplib project. + * Copyright 2019 Edward V. Emelianov , . * - * Copyright 2015 Edward V. Emelianov - * - * 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 . */ + #include "FITSmanip.h" #include "local.h" diff --git a/histogram.c b/histogram.c new file mode 100644 index 0000000..75ad085 --- /dev/null +++ b/histogram.c @@ -0,0 +1,194 @@ +/* + * This file is part of the FITSmaniplib project. + * Copyright 2019 Edward V. Emelianov , . + * + * 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 . + */ + +#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; +} diff --git a/locale/ru/LC_MESSAGES/FITSmanip.mo b/locale/ru/LC_MESSAGES/FITSmanip.mo index 69279e6..9aee15b 100644 Binary files a/locale/ru/LC_MESSAGES/FITSmanip.mo and b/locale/ru/LC_MESSAGES/FITSmanip.mo differ diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 25ea8aa..8b31176 100644 --- a/locale/ru/messages.po +++ b/locale/ru/messages.po @@ -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 \n" "Language-Team: LANGUAGE \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 "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 138b211..9a3aa10 100644 --- a/locale/ru/ru.po +++ b/locale/ru/ru.po @@ -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 \n" "Language-Team: LANGUAGE \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()!" -