simple image modification example

This commit is contained in:
eddyem 2019-02-24 16:36:41 +03:00
parent 196c1d5d09
commit a7927fc570
4 changed files with 187 additions and 20 deletions

View File

@ -17,9 +17,19 @@
*/ */
#include <fitsio.h> #include <fitsio.h>
#include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#define Stringify(x) #x
#define OMP_FOR(x) _Pragma(Stringify(omp parallel for x))
#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
/************************************************************************************** /**************************************************************************************
* fits.c * * fits.c *
**************************************************************************************/ **************************************************************************************/
@ -176,6 +186,7 @@ void table_print_all(FITS *fits);
void image_free(FITSimage **ima); void image_free(FITSimage **ima);
FITSimage *image_read(FITS *fits); FITSimage *image_read(FITS *fits);
FITSimage *image_rebuild(FITSimage *img, double *dimg);
int image_datatype_size(int bitpix, int *dtype); int image_datatype_size(int bitpix, int *dtype);
void *image_data_malloc(long totpix, int pxbytes); void *image_data_malloc(long totpix, int pxbytes);
FITSimage *image_new(int naxis, long *naxes, int bitpix); FITSimage *image_new(int naxis, long *naxes, int bitpix);

View File

@ -24,11 +24,15 @@
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <strings.h>
typedef struct{ typedef struct{
char *outfile; // output file name (for single operation) char *outfile; // output file name (for single operation)
char **infiles; // input files list char **infiles; // input files list
int Ninfiles; // input files number int Ninfiles; // input files number
char *add; // add some value to all pixels
double mult; // multiply all pixels by some value
int rmneg; // remove negative values (assign them to 0)
} glob_pars; } glob_pars;
/* /*
@ -36,6 +40,7 @@ typedef struct{
*/ */
int help; int help;
glob_pars G = { glob_pars G = {
.mult = 1.,
}; };
/* /*
@ -46,6 +51,9 @@ myoption cmdlnopts[] = {
// common options // common options
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
{"outfile", NEED_ARG, NULL, 'o', arg_string, APTR(&G.outfile), _("output file name (collect all input files)")}, {"outfile", NEED_ARG, NULL, 'o', arg_string, APTR(&G.outfile), _("output file name (collect all input files)")},
{"add", NEED_ARG, NULL, 'a', arg_string, APTR(&G.add), _("add some value (double, or 'mean', 'std', 'min', 'max')")},
{"multiply",NEED_ARG, NULL, 'm', arg_double, APTR(&G.mult), _("multiply by some value (double, operation run after adding)")},
{"rmneg", NO_ARGS, NULL, 'z', arg_none, APTR(&G.rmneg), _("remove negative values (assign them to 0)")},
end_option end_option
}; };
@ -105,6 +113,39 @@ void printstat(imgstat *stat){
printf("MEAN=%g\nSTD=%g\nMIN=%g\nMAX=%g\n", stat->mean, stat->std, stat->min, stat->max); printf("MEAN=%g\nSTD=%g\nMIN=%g\nMAX=%g\n", stat->mean, stat->std, stat->min, stat->max);
} }
bool addsomething(FITSimage *img, double *dimg, imgstat *stat){
if(!G.add || !img || !stat) return FALSE;
// parser:
char *eptr;
double val = 1., addval = 0.;
val = strtod(G.add, &eptr);
if(eptr == G.add && *G.add == '-'){++eptr; val = -1.;}
if(*eptr){ // something more
if(strncasecmp(eptr, "mean", 4) == 0) addval = stat->mean;
else if(strncasecmp(eptr, "std", 3) == 0) addval = stat->std;
else if(strncasecmp(eptr, "min", 3) == 0) addval = stat->min;
else if(strncasecmp(eptr, "max", 3) == 0) addval = stat->max;
}
if(fabs(val) > DBL_EPSILON) addval *= val;
if(fabs(addval) > DBL_EPSILON) val = addval;
DBG("Add value %g", val);
if(fabs(val) < 2.*DBL_EPSILON) return FALSE;
OMP_FOR()
for(long i = 0; i < img->totpix; ++i)
dimg[i] += val;
return TRUE;
}
bool multbysomething(FITSimage *img, double *dimg){
if(!img || !dimg) return FALSE;
if(fabs(G.mult) < 2*DBL_EPSILON) return FALSE;
DBG("multiply by %g", G.mult);
OMP_FOR()
for(long i = 0; i < img->totpix; ++i)
dimg[i] *= G.mult;
return TRUE;
}
bool process_fitsfile(char *inname, FITS *output){ bool process_fitsfile(char *inname, FITS *output){
DBG("File %s", inname); DBG("File %s", inname);
bool mod = FALSE; bool mod = FALSE;
@ -129,16 +170,39 @@ bool process_fitsfile(char *inname, FITS *output){
} }
if(!f->curHDU){ if(!f->curHDU){
WARNX("Didn't find image HDU in %s", inname); WARNX("Didn't find image HDU in %s", inname);
}else{ // OK, we have an image and can do something with it FITS_free(&f);
green("\tGet image from this HDU.\n"); return FALSE;
FITSimage *img = f->curHDU->contents.image;
double *dImg = image2double(img);
// calculate image statistics
imgstat *stat = get_imgstat(dImg, img->totpix);
printstat(stat);
//mod = TRUE;
FREE(dImg);
} }
// OK, we have an image and can do something with it
green("\tGet image from this HDU.\n");
FITSimage *img = f->curHDU->contents.image;
double *dImg = image2double(img);
// calculate image statistics
imgstat *stat = get_imgstat(dImg, img->totpix);
printstat(stat);
DBG("i[1000] = %d, o[1000]=%g", ((uint16_t*)img->data)[1000], dImg[1000]);
if(G.add){
if(addsomething(img, dImg, stat)) mod = TRUE;
}
DBG("ADD: i[1000]=%g", dImg[1000]);
if(fabs(G.mult - 1.) > DBL_EPSILON){
if(multbysomething(img, dImg)) mod = TRUE;
}
DBG("MUL: i[1000]=%g", dImg[1000]);
if(G.rmneg){
DBG("REMOVE negative values");
OMP_FOR()
for(long i = 0; i < img->totpix; ++i){
if(dImg[i] < 0.) dImg[i] = 0.;
mod = TRUE;
}
}
DBG("NEG: i[1000]=%g", dImg[1000]);
if(mod){ // modified -> change file type
image_rebuild(img, dImg);
DBG("i[1000]=%g", dImg[1000]);
}
FREE(dImg);
if(mod || output){ // file modified (or output file pointed), write differences if(mod || output){ // file modified (or output file pointed), write differences
if(!output){ if(!output){
green("Rewrite file %s.\n", f->filename); green("Rewrite file %s.\n", f->filename);
@ -166,6 +230,7 @@ int main(int argc, char *argv[]){
ofits = MALLOC(FITS, 1); ofits = MALLOC(FITS, 1);
ofits->filename = G.outfile; ofits->filename = G.outfile;
} }
initomp();
for(int i = 0; i < G.Ninfiles; ++i){ for(int i = 0; i < G.Ninfiles; ++i){
if(process_fitsfile(G.infiles[i], ofits)) mod = 1; if(process_fitsfile(G.infiles[i], ofits)) mod = 1;
} }

104
fits.c
View File

@ -940,7 +940,7 @@ int image_datatype_size(int bitpix, int *dtype){
if(dtype){ if(dtype){
switch(s){ switch(s){
case 1: // BYTE_IMG case 1: // BYTE_IMG
*dtype = TBYTE; *dtype = TBYTE; // uchar
break; break;
case 2: // SHORT_IMG case 2: // SHORT_IMG
*dtype = TUSHORT; *dtype = TUSHORT;
@ -1009,6 +1009,104 @@ FITSimage *image_new(int naxis, long *naxes, int bitpix){
return out; return out;
} }
// function for qsort
static int cmpdbl(const void *d1, const void *d2){
register double D1 = *(double*)d1, D2 = *(double*)d2;
if(fabs(D1 - D2) < DBL_EPSILON) return 0;
if(D1 > D2) return 1;
else return -1;
}
// functions to convert double to different datatypes
static void convu8(FITSimage *img, double *dimg){
uint8_t *dptr = (uint8_t*) img->data;
OMP_FOR()
for(long i = 0; i < img->totpix; ++i){
dptr[i] = (uint8_t) dimg[i];
}
}
static void convu16(FITSimage *img, double *dimg){
uint16_t *dptr = (uint16_t*) img->data;
OMP_FOR()
for(long i = 0; i < img->totpix; ++i){
dptr[i] = (uint16_t) dimg[i];
}
}
static void convu32(FITSimage *img, double *dimg){
uint32_t *dptr = (uint32_t*) img->data;
OMP_FOR()
for(long i = 0; i < img->totpix; ++i){
dptr[i] = (uint32_t) dimg[i];
}
}
static void convu64(FITSimage *img, double *dimg){
uint64_t *dptr = (uint64_t*) img->data;
OMP_FOR()
for(long i = 0; i < img->totpix; ++i){
dptr[i] = (uint64_t) dimg[i];
}
}
static void convf(FITSimage *img, double *dimg){
float *dptr = (float*) img->data;
OMP_FOR()
for(long i = 0; i < img->totpix; ++i){
dptr[i] = (float) dimg[i];
}
}
/**
* @brief image_rebuild substitute content of image with array dimg, change its output type
* @param img - input image
* @param dimg - data to change
* @return rebuilt image; array dimg no longer used an can be FREEd
*/
FITSimage *image_rebuild(FITSimage *img, double *dimg){
if(!img || !dimg) return NULL;
// first we should calculate statistics of new image
double *sr = MALLOC(double, img->totpix);
memcpy(sr, dimg, sizeof(double)*img->totpix);
qsort(sr, img->totpix, sizeof(double), cmpdbl);
double mindiff = DBL_MAX;
bool isint = TRUE;
for(long i = 1; i < img->totpix; ++i){
double d = fabs(sr[i] - sr[i-1]);
if(d > DBL_EPSILON && d < mindiff) mindiff = d;
if(fabs(d - floor(d)) > DBL_EPSILON) isint = FALSE;
}
// now we know min, max and minimal difference between elements
double min = sr[0], max = sr[img->totpix-1];
FREE(sr);
DBG("min: %g, max: %g, mindiff: %g", min, max, mindiff);
int bitpix = -64; // double by default
void (*convdata)(FITSimage*, double*) = NULL;
if(isint)do{ // check which integer type will suits better
DBG("INTEGER?");
if(min < 0){ isint = FALSE; break;} // TODO: correct with BZERO
if(max < UINT8_MAX){bitpix = 8; convdata = convu8; break; }
if(max < UINT16_MAX){bitpix = 16; convdata = convu16; break; }
if(max < UINT32_MAX){bitpix = 32; convdata = convu32; break; }
if(max < UINT64_MAX){bitpix = 64; convdata = convu64; break; }
}while(0);
if(!isint){ // float or double
DBG("mindiff: %g(%g), min: %g(%g), max: %g(%g)", mindiff,FLT_EPSILON,
min, FLT_MIN, max, FLT_MAX);
if(mindiff > FLT_EPSILON && (min > -FLT_MAX) && max < FLT_MAX){
bitpix = -32;
convdata = convf;
}
}
DBG("NOW: bitpix = %d", bitpix);
img->bitpix = bitpix;
void *data = calloc(img->totpix, abs(bitpix/8));
if(!data){ WARN("calloc()"); return NULL; }
FREE(img->data);
img->data = data;
if(convdata) convdata(img, dimg);
else memcpy(img->data, dimg, sizeof(double)*img->totpix);
img->pxsz = image_datatype_size(bitpix, &img->dtype);
return img;
}
/** /**
* build IMAGE image from data array indata * build IMAGE image from data array indata
* *
@ -1157,8 +1255,8 @@ double *image2double(FITSimage *img){
} }
uint8_t *din = img->data; uint8_t *din = img->data;
OMP_FOR() OMP_FOR()
for(size_t i = 0; i < tot; i += img->pxsz){ for(size_t i = 0; i < tot; ++i){
ret[i] = fconv(&din[i]); ret[i] = fconv(&din[i*img->pxsz]);
} }
return ret; return ret;
} }

View File

@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <float.h> // xx_EPSILON etc.
#if defined GETTEXT #if defined GETTEXT
#include <libintl.h> #include <libintl.h>
@ -33,12 +34,4 @@
#define DBL_MAX (1.7976931348623157e+308) #define DBL_MAX (1.7976931348623157e+308)
#endif #endif
#define Stringify(x) #x
#define OMP_FOR(x) _Pragma(Stringify(omp parallel for x))
#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif