From 2ca6f2c81fda4aaafc2f754241b103370241ff05 Mon Sep 17 00:00:00 2001 From: Rekhesh Mohan Date: Thu, 12 Jul 2012 21:10:31 +0530 Subject: [PATCH] Needs testing before moving this to v2 --- README.txt | 58 ++++++++++++++++++++---------- configure.ac | 5 +-- src/Makefile.am | 4 ++- src/filesys.c | 77 +++++++++++++++++++++++++++++++++++++++ src/fits2jpeg.c | 109 ++++++++++++++++++++++++++++++++++---------------------- src/fits2jpeg.h | 10 +++++- src/image.c | 44 ++++++++++++++++------- src/messages.c | 26 ++++++++------ 8 files changed, 246 insertions(+), 87 deletions(-) create mode 100644 src/filesys.c diff --git a/README.txt b/README.txt index c5f5ca1..eeace20 100644 --- a/README.txt +++ b/README.txt @@ -80,10 +80,12 @@ named `INSTALL.txt'. ------- Usage: fits2jpeg [options] - - Options are: + You need to specify a fits image file for this program to + work. Everything else is optional. A brief description of them are + listed below: -h help + Prints out a usage-help message, much like this section. -s scale for output image, where can be: @@ -95,6 +97,19 @@ named `INSTALL.txt'. normalize for linear histogram stretch equalize for histogram equalization + -n + Negate the image + + -q + quality factor. Defines the jpeg encoding quality + Valid range: 0-100, default value: 100, which means + best quality and largest file-size. + + -d + Write jpeg file to this specified directory. Will + create it if needed. Default is to write jpeg in the + same directory of fits image file + -r : Clip output image to min-max range. Eg: 0:100 Use only values in the range 0-100 @@ -102,22 +117,18 @@ named `INSTALL.txt'. :10 Clip everything above 10 10: Clip everything below 10 - -n - Negate the image. - - -q - jpeg quality factor. Defines the jpeg encoding quality - Valid range: 0-100, default value: 100, which is for - best quality (and largest file size). - -z Resize/Scale output image by . Eg: 0.5 Shrink output to half of input 2.0 Magnify output to double the size + Allowed range: 0.01 to 4.0 + NOTE: Zooming will be carried out after all other + operations, before writing out jpeg image fits2jpeg uses a bilinear interpolation based algorithm to scale the image. Allowed range: 0.01 to 4.0 NOTE: Anything outside the allowed range will be clipped + to this range. Output will be written to .jpg. For eg., @@ -128,23 +139,33 @@ named `INSTALL.txt'. Wild card entries allowed in . For eg: *.fits, m31*.fits ngc???.fits etc. - More examples: +3.1 Examples: +------------- i. fits2jpeg -s log sirius.fits + will write out sirius.jpg, flux/intensity in log scale ii. fits2jpeg -s sqroot *.fits - Converts all fits files in the directory to jpegs, with - square-root scaling of flux/intensity - Good for very - high dynamic range images + + Converts all fits files in the directory to jpegs, with square-root scaling + of flux/intensity - Good for very high dynamic range images iii. fits2jpeg -n ngc4151.fits + Converts ngc4151.fits to ngc4151.jpg, negative image. -iv. fits2jpeg -s square -n -r 10:2000 m31.fits - Write out m31.jpg, after square scaling of flux/intensity, - negate image and clip pixel values in the range 10 to 2000 - units. + iv. fits2jpeg -s square -n -r 10:2000 m31.fits + + Write out m31.jpg, after square scaling of flux/intensity, negate image and + clip pixel values in the range 10 to 2000 units. + + v. fits2jpeg -s equalize -r 200: -d/path/to/mydir NGS253*.fits + + Reads all fits files in the present directory that matches the filename + patterm, performs a histogram equalization, drops pixel values below 200 + and write out all the corresponding jpeg files to directory /path/to/mydir + Will create the destination directory tree if it does not exist. 3.1. Sequence of operations @@ -158,6 +179,7 @@ Here is the sequence of operations, after reading the fits file: v. Image zoom - magnify or shrink the image vi. Write out jpeg file + 3. DOCUMENTATION ---------------- An extensive coverage of how this program works along with line by line account diff --git a/configure.ac b/configure.ac index 770550d..ef21fc7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([CADS_fits2jpeg], [1.95], [cads@iiap.res.in]) +AC_INIT([CADS_fits2jpeg], [1.99], [cads@iiap.res.in]) AC_LANG_C AM_INIT_AUTOMAKE([-Wall -Werror]) AC_CONFIG_SRCDIR([config.h.in]) @@ -13,7 +13,8 @@ AC_PROG_MAKE_SET # Checks for libraries. # Checks for header files. -AC_CHECK_HEADERS([string.h math.h float.h ctype.h libgen.h dirent.h]) +#AC_CHECK_HEADERS([string.h math.h float.h ctype.h libgen.h dirent.h]) +#AC_CHECK_HEADERS([sys/stat.h sys/types.h]) # Checks for typedefs, structures, and compiler characteristics. diff --git a/src/Makefile.am b/src/Makefile.am index 1e368c7..148dfb3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,5 @@ bin_PROGRAMS = fits2jpeg -fits2jpeg_SOURCES = fits2jpeg.c messages.c getopt.c image.c signal_handler.c +fits2jpeg_SOURCES = fits2jpeg.c image.c \ + messages.c filesys.c \ + getopt.c signal_handler.c noinst_HEADERS = fits2jpeg.h \ No newline at end of file diff --git a/src/filesys.c b/src/filesys.c new file mode 100644 index 0000000..873f891 --- /dev/null +++ b/src/filesys.c @@ -0,0 +1,77 @@ +/*************************************************************************** + * This file is a part of CADS/UVS fits2jpeg conversion software * + * Copyright (C) 2012 by CADS/UV Software Team, * + * Indian Institute of Astrophysics * + * Bangalore 560034 * + * cads_AT_iiap.res.in * + * * + * 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 * + * (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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +/*Header Definitions*/ +#include "fits2jpeg.h" + +/*---------------------------------------------------------------------------*/ +int make_dir(char * folder, mode_t mode) +{ + struct stat st; + int status = 0; + + if (stat(folder, &st) != 0) + { + /* Directory does not exist - make it */ + status = mkdir(folder, mode); + if (status) return status; + } + else if (!S_ISDIR(st.st_mode)) + return status = -1; + return status; +} + +int make_tree(char * folder, mode_t mode) +{ + char *pp; + char *sp; + int status = 0; + char *fpath = strdup(folder); + + pp = fpath; + + while (status == 0 && (sp = strchr(pp, '/')) != 0) + { + if (sp != pp) + { + *sp = '\0'; + status = make_dir(fpath, mode); + *sp = '/'; + } + pp = sp + 1; + } + + if (status == 0) status = make_dir(folder, mode); + return status; +} + +char *strdup(const char *str) +{ + int n = strlen(str) + 1; + char *dup = malloc(n); + if(dup) + { + strcpy(dup, str); + } + return dup; +} diff --git a/src/fits2jpeg.c b/src/fits2jpeg.c index cc97e08..7390330 100644 --- a/src/fits2jpeg.c +++ b/src/fits2jpeg.c @@ -1,4 +1,5 @@ /*************************************************************************** + * This file is a part of CADS/UVS fits2jpeg conversion software * * Copyright (C) 2012 by CADS/UV Software Team, * * Indian Institute of Astrophysics * * Bangalore 560034 * @@ -78,9 +79,8 @@ 5. jpeg quality factor 6. pixel scaling operations moved to image.c 7. Image resizing - TODO - 1. move fits read to image.c - 2. specify output directory + 8. moved fits read to image.c + 9. Option to specify output directory *---------------------------------------------------------------------------*/ #include "fits2jpeg.h" @@ -91,55 +91,80 @@ int optindex; /*--------------------------- Begin Main Progam -----------------------------*/ int main(int argc, char *argv[], char *envp[]) { - fitsfile *fptr; - - int scale = 0, status = 0, jpgqual = 100, nfound, anynull; - unsigned int i = 0, j = 0, usrclip = 0, usrnegt = 0, usrzoom = 0; - long xdim = 0, ydim = 0, naxes[2], row_stride; + int scale = 0, jpgqual = 100, status = 0; + unsigned int i = 0, j = 0; + unsigned int customdir = 0, usrclip = 0, usrnegt = 0, usrzoom = 0; + long xdim = 0, ydim = 0, row_stride; unsigned long npixels = 0; - float datamin = 0.0, datamax = 0.0, nullval = 0.0, zoomfact = 1.0; + float datamin = 0.0, datamax = 0.0, zoomfact = 1.0; float *data; char jpeg_file_name[MAX_TEXT] = "", fits_file_name[MAX_TEXT] = ""; + char output_dir[MAX_TEXT] = ""; char *tmpstr, *sptr; int opt; /* For getopt */ extern char *optarg; extern int optindex; - + mode_t mode = 0755; FILE *jpeg_file; - struct jpeg_error_mgr jerr; struct jpeg_compress_struct cinfo; JSAMPROW row_pointer[1]; JSAMPLE *image_buffer; /*---------------- End of variable initialization -----------------------*/ - PRINT_BANNER(); /* Header: Talks about program, version & purpose */ + banner(); /* Header: Talks about program, version & purpose */ set_signals(); /* Trap un-natural exits */ /*-------------------- Parse command line inputs ------------------------*/ if (argc < 2) usage(); /* People who don't give any arguments need help */ - while ( ( opt = my_getopt ( argc, argv, "e:hnq:r:s:z:" ) ) != EOF ) + while ( ( opt = my_getopt ( argc, argv, "d:e:hnq:r:s:z:" ) ) != EOF ) switch ( opt ) { case 's': - if (strcmp(optarg, "linear") ==0) scale = 0; - else if (strcmp(optarg, "sqroot") ==0) scale = 1; - else if (strcmp(optarg, "square") ==0) scale = 2; - else if (strcmp(optarg, "cubic") ==0) scale = 3; - else if (strcmp(optarg, "log") ==0) scale = 4; - else if (strcmp(optarg, "normalize")==0) scale = 5; - else if (strcmp(optarg, "equalize") ==0) scale = 6; + if (strcmp(optarg, "linear") == 0) scale = 0; + else if (strcmp(optarg, "sqroot") == 0) + { + printinfo("Using square-root scale"); + scale = 1; + } + else if (strcmp(optarg, "square") == 0) + { + printinfo("Using quadratic scale"); + scale = 2; + } + else if (strcmp(optarg, "cubic") == 0) + { + printinfo("Using cubic scale"); + scale = 3; + } + else if (strcmp(optarg, "log") == 0) + { + printinfo("Using log scale"); + scale = 4; + } + else if (strcmp(optarg, "normalize") == 0) + { + printinfo("Performing histogram stretch (normalization)"); + scale = 5; + } + else if (strcmp(optarg, "equalize") == 0) + { + printinfo("Performing Histogram Equalization"); + scale = 6; + } else + { printwarn(strcat(optarg, " -- Unrecognized option")); scale = 0; + } break; case 'e': /* Need to preserve it for backward compatibility */ - if (strcmp(optarg, "normalize")==0) scale = 5; - else if (strcmp(optarg, "equalize") ==0) scale = 6; + if (strcmp(optarg, "normalize") == 0) scale = 5; + else if (strcmp(optarg, "equalize") == 0) scale = 6; else printerro(strcat(optarg, " -- Unrecognized option")); break; @@ -182,16 +207,21 @@ int main(int argc, char *argv[], char *envp[]) break; case 'z' : - - /* Do something to scale image - */ zoomfact = atof(optarg); - zoomfact = abs(zoomfact); + zoomfact = fabs(zoomfact); if (zoomfact < 0.01) zoomfact = 0.01; if (zoomfact > 4.0) zoomfact = 4.0; usrzoom = 1; break; + case 'd': + strcpy(output_dir, optarg); + printf("INFO : Output image directory is %s\n", output_dir); + customdir = 1; + status = make_tree(output_dir, mode); + if (status != 0) printerro("Unable to create output directory"); + break; + case 'h': usage(); break; @@ -200,7 +230,7 @@ int main(int argc, char *argv[], char *envp[]) printerro("You can try 'fits2jpeg -h' for valid options"); break; } - + if (scale == 0) printinfo("Using linear scale"); if ((argc - optindex) == 0) usage(); /* Someone gave only options */ /*---------------------- Begin processing files -------------------------*/ @@ -219,22 +249,18 @@ int main(int argc, char *argv[], char *envp[]) strtok(jpeg_file_name, "."); strcat(jpeg_file_name, ".jpg"); - fits_open_file(&fptr, fits_file_name, READONLY, &status); - fits_read_keys_lng(fptr, "NAXIS", 1, 2, naxes, &nfound, &status); - if (status) - printerro(strcat(fits_file_name, " <-- Failed to open the file")); + if (customdir == 1) + { + if (output_dir[strlen(output_dir) - 1] != '/') + strcat(output_dir, "/"); - /* Read in data */ - npixels = naxes[0] * naxes[1]; - data = malloc(sizeof(float) * npixels); + strcat(output_dir, basename(jpeg_file_name)); + strcpy(jpeg_file_name, output_dir); + } - nullval = 0; - if (fits_read_img(fptr, TFLOAT, 1, npixels, &nullval, data, &anynull, - &status)) - printerro(strcat(fits_file_name, " has no valid fits image data")); + read_fits(fits_file_name, &xdim, &ydim, &data); + npixels = xdim * ydim; - fits_close_file(fptr, &status); - /*Close data file*/ printf("INFO : data input from %s\n", fits_file_name); @@ -262,8 +288,6 @@ int main(int argc, char *argv[], char *envp[]) for (i = 0; i < npixels; ++i) image_buffer[i] ^= 0xff; } - xdim = naxes[0]; - ydim = naxes[1]; if (usrzoom == 1) { printf("INFO : Image zoom factor = %3.2f\n", zoomfact); @@ -272,6 +296,7 @@ int main(int argc, char *argv[], char *envp[]) /*Write out data into JPEG file*/ jpeg_file = fopen(jpeg_file_name, "wb");/* Open JPEG file for writing*/ + if (!jpeg_file) printerro("Unable to create output file"); cinfo.err = jpeg_std_error(&jerr); /* JPEG error handler */ jpeg_create_compress(&cinfo); /* JPEG initialization */ jpeg_stdio_dest(&cinfo, jpeg_file); /* Send compressed data to stdio */ diff --git a/src/fits2jpeg.h b/src/fits2jpeg.h index 3920d82..accff93 100644 --- a/src/fits2jpeg.h +++ b/src/fits2jpeg.h @@ -32,22 +32,30 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include #define PROGRAM "fits2jpeg" #define r2d (90./atan2(1,0)) #define MAX_TEXT 1024 int my_getopt(int, char * const *, const char *); -void PRINT_BANNER(void); +int make_dir(char *, mode_t); +int make_tree(char *, mode_t); +void banner(void); void usage(void); void signals_handler(int); void set_signals(void); void printinfo(const char *); void printwarn(const char *); void printerro(const char *); +void read_fits(char *, long *, long *, float **); void scale_pixels(int, unsigned int, float *, JSAMPLE **); void resize_image(long *, long *, float, JSAMPLE **); +char *strdup(const char *); diff --git a/src/image.c b/src/image.c index f5f6c46..6c48d67 100644 --- a/src/image.c +++ b/src/image.c @@ -24,6 +24,34 @@ /*Header Definitions*/ #include "fits2jpeg.h" +void read_fits(char * fits_file_name, long * xdim, long * ydim, float ** data) +{ + fitsfile *fptr; + int status = 0, nfound, anynull; + long naxes[2]; + long npixels; + float nullval = 0.0; + + fits_open_file(&fptr, fits_file_name, READONLY, &status); + fits_read_keys_lng(fptr, "NAXIS", 1, 2, naxes, &nfound, &status); + if (status) + printerro(strcat(fits_file_name, " <-- Failed to open the file")); + + /* Read in data */ + npixels = naxes[0] * naxes[1]; + (*data) = malloc(sizeof(float) * npixels); + + nullval = 0; + if (fits_read_img(fptr, TFLOAT, 1, npixels, &nullval, (*data), &anynull, + &status)) + printerro(strcat(fits_file_name, " has no valid fits image data")); + + *xdim = naxes[0]; + *ydim = naxes[1]; + + fits_close_file(fptr, &status); +} + /*---------------------------------------------------------------------------* * SCALE_PIXELS: Changes the pixel scale to linear/log/sqroot/etc.. *---------------------------------------------------------------------------*/ @@ -89,39 +117,32 @@ void scale_pixels(int scale, unsigned int npixels, float *data, switch (scale) { case 1 : /* Square root */ - printinfo("Using square-root scale"); scl_data = sqrt((float)JMAXVAL)/(float)JMAXVAL; for (i = 0; i < npixels; ++i) (*image_buffer)[i] = (int)(sqrt(data[i])/scl_data); break; case 2 : /* Square */ - printinfo("Using quadratic scale"); scl_data = pow((float)JMAXVAL,2)/(float)JMAXVAL; for (i = 0; i < npixels; ++i) (*image_buffer)[i] = (int)abs((pow(data[i],2) - 1.0)/scl_data); break; case 3 : /* Cubic */ - printinfo("Using cubic scale"); scl_data = pow((float)JMAXVAL,3)/(float)JMAXVAL; for (i = 0; i < npixels; ++i) (*image_buffer)[i] = (int)abs((pow(data[i],3) - 1.0)/scl_data); break; case 4 : /* log */ - printinfo("Using log scale"); scl_data = log(1.0 + (float)JMAXVAL)/(float)JMAXVAL; for (i = 0; i < npixels; ++i) (*image_buffer)[i] = (int)((log(abs(data[i]) + 1.0))/scl_data); break; - case 5 : - /* contrast stretch */ - printinfo("Performing histogram stretch (normalization)"); - + case 5 : /* contrast stretch */ /* We need to go through the cumulative histogram to pick the - * appropriate values for datamin and datamax */ + * appropriate values for datamin and datamax */ i = 0; while (i < JMAXVAL) { @@ -155,14 +176,11 @@ void scale_pixels(int scale, unsigned int npixels, float *data, } break; - case 6 : - /* histogram equalization */ - printinfo("Performing Histogram Equalization"); + case 6 : /* histogram equalization */ for (i = 0; i < npixels; ++i) (*image_buffer)[i] = cumhist[(*image_buffer)[i]] * JMAXVAL; break; default : - printinfo("Using linear scale"); break; } } diff --git a/src/messages.c b/src/messages.c index 75f890c..ed4063e 100644 --- a/src/messages.c +++ b/src/messages.c @@ -25,7 +25,7 @@ #include "fits2jpeg.h" /*---------------------------------------------------------------------------*/ -void PRINT_BANNER() +void banner() { printf("\n"); printf(" %s %s\n", PROGRAM, VERSION); @@ -36,8 +36,10 @@ void PRINT_BANNER() void usage() { printf ("\n Usage: fits2jpeg [options] \n"); - printf (" Options are: \n"); + printf (" Name of fits image file is mandatory.\n"); + printf (" Optional parameters are listed below: \n\n"); printf (" -h help \n"); + printf (" Print this help message and exit \n\n"); printf (" -s \n"); printf (" scale for output image, where can be: \n"); printf (" linear Linear scale, default \n"); @@ -46,25 +48,29 @@ void usage() printf (" cubic for cubic scale \n"); printf (" log for log scale \n"); printf (" normalize for linear histogram stretch \n"); - printf (" equalize for histogram equalization \n"); + printf (" equalize for histogram equalization \n\n"); + printf (" -n \n"); + printf (" Negate the image \n\n"); + printf (" -q \n"); + printf (" quality factor. Defines the jpeg encoding quality \n"); + printf (" Valid range: 0-100, default value: 100 (max.quality)\n\n"); + printf (" -d \n"); + printf (" Write jpeg file to this specified directory. Will \n"); + printf (" create it if needed. Default is to write jpeg in the\n"); + printf (" same directory as fits image file \n\n"); printf (" -r : \n"); printf (" Clip output image to min-max range. Eg: \n"); printf (" 0:100 Use only values in the range 0-100 \n"); printf (" 100:0 Same as above, but negative image \n"); printf (" :10 Clip everything above 10 \n"); - printf (" 10: Clip everything below 10 \n"); - printf (" -n \n"); - printf (" Negate the image \n"); - printf (" -q \n"); - printf (" quality factor. Defines the jpeg encoding quality \n"); - printf (" Valid range: 0-100, default value: 100 (max.quality)\n"); + printf (" 10: Clip everything below 10 \n\n"); printf (" -z \n"); printf (" Resize/Scale output image by . Eg: \n"); printf (" 0.5 Shrink output to half of input \n"); printf (" 2.0 Magnify output to double the size \n"); printf (" Allowed range: 0.01 to 4.0 \n"); printf (" NOTE: Zooming will be carried out after all other \n"); - printf (" operations, before writing out jpeg image \n"); + printf (" operations, before writing out jpeg image \n\n"); printf (" Output will be written to .jpg. Wild card\n"); printf (" entries allowed in ; For eg: *.fits, m31*.fits\n"); printf (" ngc???.fits etc. \n"); -- 2.12.1