summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e9b7faa)
raw | patch | inline | side by side (parent: e9b7faa)
author | Rekhesh Mohan <reks@iiap.res.in> | |
Thu, 12 Jul 2012 15:58:07 +0000 (21:28 +0530) | ||
committer | Rekhesh Mohan <reks@iiap.res.in> | |
Thu, 12 Jul 2012 15:58:07 +0000 (21:28 +0530) |
ChangeLog.txt | patch | blob | history | |
README.txt | patch | blob | history | |
configure.ac | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/filesys.c | [new file with mode: 0644] | patch | blob |
src/fits2jpeg.c | patch | blob | history | |
src/fits2jpeg.h | [new file with mode: 0644] | patch | blob |
src/image.c | [new file with mode: 0644] | patch | blob |
src/messages.c | [new file with mode: 0644] | patch | blob |
diff --git a/ChangeLog.txt b/ChangeLog.txt
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
------------------------------------------------------------------------
NOTE: This file records the changes made after the release of the stable
-version fits2jpeg-1.0
+version fits2jpeg-1.0
------------------------------------------------------------------------
+
+
+
+Updates in 2.0 Release
+----------------------
+
+ 1. Merged scale & operations to single flag
+ v1.0 had normalize/equalize handled by "-e" flag and rest of
+ image operations by "-s" flag. Both are merged into "-s" in
+ this release.
+
+ 2. New option to clip image min/max
+ You can limit the pixel-values in output image using the flag
+ "-r". For eg: -r 10:300 to generate jpegs with pixel values in
+ the range 10 to 300.
+
+ 3. New option to negate image option
+ A negative image can be generated using "-n" flag.
+
+ 4. New option to resize image
+ zoom or shrink output image by "-z <zoomfact>".
+
+ 5. New option to choose jpeg quality factor
+ You can choose the jpeg quality factor by "-q <quality>"
+ Quality factor was fixed at 100 in previous release.
+
+ 6. New option to specify output directory for saving jpeg images
+ Output location can be specified by "-d </path/to/folder>"
+ If the target directory does not exist, the whole tree will be
+ created.
diff --git a/README.txt b/README.txt
--- a/README.txt
+++ b/README.txt
0. FEATURES
-----------
-fits2jpeg is a tiny program to read FITS Images and convert them
-to jpeg, which is more popular. This software supports various
-type of intensity scaling and image enhancements. fits2jpeg do not
-support coordinate axes overlay. fits2jpeg supports batch mode
-operations - for instance, converting several fits files to jpeg
-at once.
+fits2jpeg is a tiny program to read FITS Images and convert them to jpeg, which
+is more popular. This software supports various type of intensity scaling and
+image enhancements. fits2jpeg do not support coordinate axes overlay. fits2jpeg
+supports batch mode operations - for instance, converting several fits files to
+jpeg at once.
1. BUILD/INSTALL
http://heasarc.gsfc.nasa.gov/docs/software/fitsio/fitsio.html
b) JPEGLIB
- jpeg library and headers. libjpeg is installed by default on most
- platforms, but we need the header files too. Once you have cfitsio
- and jpeglib installed, you may proceed with compiling jpeg2fits.
+ jpeg library and headers. libjpeg is installed by default on most platforms,
+ but we need the header files too. Once you have cfitsio and jpeglib
+ installed, you may proceed with compiling jpeg2fits.
+
Follow these 4 steps:
2. Type `make' to compile the package.
3. Type `make install' to install the programs and any data files and
- documentation. By default, the binary is copied to /usr/local/bin.
- You may change this destination by passing on the following
- argument to configure:
+ documentation. By default, the binary is copied to /usr/local/bin. You may
+ change this destination by passing on the following argument to configure:
--prefix=/your/chosen/destination
Which would result in the binary in /your/chosen/destination/bin
You may need to ensure that in $PATH to run the program.
- 4. You can remove the program binaries and object files from the
- source code directory by typing `make clean'.
+ 4. You can remove the program binaries and object files from the source code
+ directory by typing `make clean'.
-You may read more about configure script and others in the accompanying
-file named `INSTALL.txt'.
+You may read more about configure script and others in the accompanying file
+named `INSTALL.txt'.
2.USAGE
-------
- fits2jpeg [options] <fits_file>
+ Usage: fits2jpeg [options] <fits_file>
+ You need to specify a fits image file <fits_file> for this program to
+ work. Everything else is optional. A brief description of them are
+ listed below:
- Options are:
-h help
+ Prints out a usage-help message, much like this section.
-s <scale_type>
- scale for output image intensity. Valid arguments are:
-
- linear for linear scaling, default
+ scale for output image, where <scale_type> can be:
+ linear Linear scale, default
sqroot for square root scale
square for quadratic scale
cubic for cubic scale
log for log scale
-
- -e <operation>
- Imaghe enhancement operations. Valid arguments are:
-
- equalize perform histogram equalization
- normalize perform a linear contrast stretch
- (use cutoffs at 1% and 99% for image data)
+ normalize for linear histogram stretch
+ equalize for histogram equalization
+
+ -n
+ Negate the image
+
+ -q <value>
+ quality factor. Defines the jpeg encoding quality
+ Valid range: 0-100, default value: 100, which means
+ best quality and largest file-size.
+
+ -d <path/to/output/directory>
+ 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 <min>:<max>
+ Clip output image to min-max range. Eg:
+ 0:100 Use only values in the range 0-100
+ 100:0 Same as above, but negative image
+ :10 Clip everything above 10
+ 10: Clip everything below 10
+
+ -z <zoomfactor>
+ Resize/Scale output image by <zoomfactor>. 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 <fits_file_root>.jpg. For eg.,
writes output to jpeg file 30dor.jpg
- Wild card entries allowed in <fits_file>. For eg: *.fits,
- m31*.fits ngc???.fits etc.
+ Wild card entries allowed in <fits_file>. For eg: *.fits, m31*.fits
+ ngc???.fits etc.
- More examples:
- i. fits2jpeg -s cubic sirius.fits
+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
-iii. fits2jpeg -e normalize ngc4151.fits
- Converts ngc4151.fits to ngc4151.jpg, contrast stretched.
+ 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.
-NOTE: You can perform scaling + enhancing on an image. Scaling will
- always be performed first. In most cases combining these two
- would lead to un-usable images :)
+ 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
+---------------------------
+Here is the sequence of operations, after reading the fits file:
+
+ i. clip the image to user specified pixel limits, if it was requested
+ ii. Squeeze image pixel values to jpeg limits (0 - 255)
+ iii. image scaling function, default being linear pixel scale
+ iv. Negate the image, if requested
+ 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 of the happenings within the code, are dealt with
-in the user manual, which is yet to be written :(
+An extensive coverage of how this program works along with line by line account
+of the happenings within the code, are dealt with in the user manual, which is
+yet to be written :(
4. LICENSE: GPL [See the file COPYING.txt for details]
5. DISCLAIMER
-------------
-You may encounter bugs in this software. If you do, please
-report them. Your bug reports are valuable contributions,
-since they allow us to notice and fix problems on
-machines/platforms we don't have, and/or remained un-noticed.
+You may encounter bugs in this software. If you do, please report them. Your bug
+reports are valuable contributions, since they allow us to notice and fix
+problems on machines/platforms we don't have, and/or remained un-noticed.
6. REPORTING BUGS
Either way, please include as many details as possible.
+
-----------------------------------------------------------
Reks, 28 June 2012 <reks_at_iiap.res.in>
- Last modified: 28 June 2012
+ Last modified: 10 July 2012
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
-AC_INIT([CADS_fits2jpeg], [1.0], [cads@iiap.res.in])
+AC_INIT([CADS_fits2jpeg], [2.0], [cads@iiap.res.in])
AC_LANG_C
AM_INIT_AUTOMAKE([-Wall -Werror])
AC_CONFIG_SRCDIR([config.h.in])
# Checks for libraries.
# Checks for header files.
-AC_CHECK_HEADERS([stdio.h stdlib.h string.h math.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.
+
# Checks for library functions.
AC_FUNC_MALLOC
LIBS="$LIBS -L/usr/lib64 -L/usr/lib -lm -ljpeg -lcfitsio"
-CFLAGS="-ansi $CFLAGS -I/usr/include -I/usr/include/cfitsio"
+CFLAGS="-ansi -Wall $CFLAGS -I/usr/include -I/usr/include/cfitsio"
#---------------------------------------------------------------------#
# Now we check for cfitsio headers and library #
#---------------------------------------------------------------------#
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
bin_PROGRAMS = fits2jpeg
-fits2jpeg_SOURCES = fits2jpeg.c getopt.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
--- /dev/null
+++ b/src/filesys.c
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * 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"
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*
+ * MAKE_DIR: Wrapper to mkdir() with some basic error checks
+ *---------------------------------------------------------------------------*/
+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;
+}
+
+/*---------------------------------------------------------------------------*
+ * MAKE_TREE: moves through a directory path and creates directories and
+ * subdirectories using make_dir(), top-down.
+ *---------------------------------------------------------------------------*/
+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;
+}
+
+/*---------------------------------------------------------------------------*
+ * STRDUP: This one is not a part of ANSI-strict, so we had to write one
+ *---------------------------------------------------------------------------*/
+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
--- a/src/fits2jpeg.c
+++ b/src/fits2jpeg.c
/***************************************************************************
+ * 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 *
Reconstruction and additional features: Reks
*---------------------------------------------------------------------------*/
+
/*---------------------------------------------------------------------------
Modification History
Reks 28 June 2012
1. rebranded to CADS/UVS
- *-------------------------------------------------------------------------*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/*Header Definitions*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <libgen.h>
-#include <dirent.h>
-#include <fitsio2.h>
-#include <jpeglib.h>
-
-#define PROGRAM "fits2jpeg"
-#define r2d (90./atan2(1,0))
-#define MAX_TEXT 150
-int my_getopt(int, char * const *, const char *);
-void signals_handler(int);
-void set_signals(void);
+
+ Reks 05-10 July 2012 v2.0 plans
+ 1. Merged scale & operations to single flag
+ 2. added fits2jpeg.h, help/banner functions moved to messages.c
+ 3. Options to clip image min/max
+ 4. negate image option
+ 5. jpeg quality factor
+ 6. pixel scaling operations moved to image.c
+ 7. Image resizing
+ 8. moved fits read to image.c
+ 9. Option to specify output directory
+ *---------------------------------------------------------------------------*/
+
+#include "fits2jpeg.h"
char *optarg;
int optindex;
-/*---------------------------------------------------------------------------*/
-void PRINT_BANNER()
-{
- printf("\n");
- printf(" %s %s\n", PROGRAM, VERSION);
- printf(" Converts fits image files to jpeg\n");
- printf("-----------------------------------------------------------\n");
-}
-/*---------------------------------------------------------------------------*/
-void usage()
-{
- printf ("\n Usage: fits2jpeg [-s <options>] <fits_file> \n");
- printf (" Options are: \n");
- printf (" -h help \n");
- printf (" -s <scale_type> \n");
- printf (" scale for output image, where <scale_type> can be: \n");
- printf (" linear Linear scale, default \n\n");
- printf (" sqroot for square root scale \n");
- printf (" square for quadratic scale \n");
- printf (" cubic for cubic scale \n");
- printf (" log for log scale \n");
- printf (" -e <operation> \n");
- printf (" Image enhancements, where <operation> can be: \n");
- printf (" normalize for linear histogram stretch \n");
- printf (" equalize for histogram equalization \n");
- printf (" Output will be written to <fits_file_root>.jpg. Wild card\n");
- printf (" entries allowed in <fits_file>; For eg: *.fits, m31*.fits\n");
- printf (" ngc???.fits etc. \n");
- printf ("-----------------------------------------------------------\n");
- printf ("Copyright (c) 2012 The CADS Team, IIAp. [GPL v3.0 or later]\n");
- printf ("Report Bugs to: http://cads.iiap.res.in/bugzilla \n");
- printf ("Documentation : http://cads.iiap.res.in/software \n\n");
- exit(1);
-}
-/*---------------------------------------------------------------------------*/
/*--------------------------- Begin Main Progam -----------------------------*/
int main(int argc, char *argv[], char *envp[])
{
- fitsfile *fptr;
-
- int scale = 0, process = 0, status = 0, nfound, anynull;
- unsigned int i = 0, j = 0, npixels = 0;
- long naxes[2], row_stride;
- float datamin = 0.0, datamax = 0.0;
- float nullval = 0.0, scl_data;
+ 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, zoomfact = 1.0;
float *data;
- float tmp = 0.0;
- float hist[256] = {0.0}, cumhist[256] = {0.0};
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;
- int JMAXVAL = 255; /* Max value for greyscale in jpeg */
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, "s:e:h" ) ) != EOF )
+ while ( ( opt = my_getopt ( argc, argv, "d:e:hnq:r:s:z:" ) ) != EOF )
switch ( opt )
{
case 's':
- if (strcmp(optarg, "sqroot") ==0) scale = 1;
- if (strcmp(optarg, "square") ==0) scale = 2;
- if (strcmp(optarg, "cube") ==0) scale = 3;
- if (strcmp(optarg, "log") ==0) scale = 4;
+ 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':
- if (strcmp(optarg, "normalize")==0) process = 1;
- if (strcmp(optarg, "equalize") ==0) process = 2;
+ /* Need to preserve it for backward compatibility */
+ if (strcmp(optarg, "normalize") == 0) scale = 5;
+ else if (strcmp(optarg, "equalize") == 0) scale = 6;
+ else
+ printerro(strcat(optarg, " -- Unrecognized option"));
+ break;
+
+ case 'r':
+ tmpstr = optarg; /* make a copy.. and leave optarg alone */
+ sptr = strpbrk(tmpstr, ":"); /* Find the delimiter */
+ if (sptr == NULL)
+ printerro("Expected a ':' as separator for min/max");
+
+ if (sptr+1 == tmpstr + strlen(tmpstr)) /* -c <datamin>: */
+ datamax = FLT_MAX;
+ else
+ datamax = atof(sptr+1);
+
+ /* There should be an easier way to find datamin alongside datamax,
+ * but I am too sleepy to try anything now */
+ sptr = strchr(tmpstr, ':');
+ if (sptr == tmpstr) /* -c :<datamax> */
+ datamin = -1.0*FLT_MAX;
+ else
+ {
+ sptr = strtok(tmpstr, ":");
+ datamin = atof(sptr);
+ }
+
+ /* Remember.. now we have user specified range */
+ usrclip = 1;
+ break;
+
+ case 'n' :
+ usrnegt = 1;
+ break;
+
+ case 'q' :
+ jpgqual = atoi(optarg);
+ if (jpgqual < 0) jpgqual = 0;
+ if (jpgqual > 100) jpgqual = 100;
+ printf("INFO : jpeg quality factor changed to %d\n", jpgqual);
+ break;
+
+ case 'z' :
+ zoomfact = atof(optarg);
+ 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;
- case '*':
- usage();
+ default :
+ printerro("You can try 'fits2jpeg -h' for valid options");
break;
}
-
- if ((argc - optindex) == 0) usage(); /* Somebody gave only options */
+ if (scale == 0) printinfo("Using linear scale");
+ if ((argc - optindex) == 0) usage(); /* Someone gave only options */
/*---------------------- Begin processing files -------------------------*/
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)
- {
- fprintf(stderr, "ERROR : Could not open file: %s\n",
- fits_file_name);
- exit(EXIT_FAILURE);
- }/*Endif*/
-
- /* Read in data */
- npixels = naxes[0] * naxes[1];
- data = (float *) malloc(sizeof(float) * npixels);
-
- nullval = 0;
- if (fits_read_img(fptr, TFLOAT, 1, npixels, &nullval, data, &anynull,
- &status))
+ if (customdir == 1)
{
- fprintf(stderr, "ERROR : No valid fits image data in %s\n",
- fits_file_name);
- exit(EXIT_FAILURE);
- }/*Endif*/
+ if (output_dir[strlen(output_dir) - 1] != '/')
+ strcat(output_dir, "/");
- fits_close_file(fptr, &status);
- /*Close data file*/
- printf("INFO : data input from %s\n", fits_file_name);
-
- /* find min & max in image */
- datamax = -1.0e9;
- datamin = +1.0e9;
- for (i = 0; i < npixels; ++i)
- {
- if (data[i] > datamax) datamax = data[i];
- if (data[i] < datamin) datamin = data[i];
- } /*endfor*/
+ strcat(output_dir, basename(jpeg_file_name));
+ strcpy(jpeg_file_name, output_dir);
+ }
- /* Convert data into bytscaled values for jpeg file */
- /* the dynamic range is reduced to 255 for jpeg */
- scl_data = (datamax - datamin)/(float)JMAXVAL;
- for (i = 0; i < npixels; ++i)
- data[i] = (data[i] - datamin)/scl_data;
+ read_fits(fits_file_name, &xdim, &ydim, &data);
+ npixels = xdim * ydim;
- /* All data is now squeezed into the range 0 - 255 */
- /* NOTE: At this point onwards min & max is 0 and 255 respectively */
+ printf("INFO : data input from %s\n", fits_file_name);
/* Now we need to look at user options.. */
- /* 1. scale it as per user's requirement. */
- /* 2. image enhancing operations */
- /* Allocate image buffer */
- image_buffer = (unsigned char *) malloc(sizeof(char) * npixels);
- scl_data = 1.0;
- switch (scale)
- {
- case 1 : /* Square root */
- printf("INFO : Using square-root scale\n");
- 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 */
- printf("INFO : Using quadratic scale\n");
- 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 */
- printf("INFO : Using cubic scale\n");
- 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 */
- printf("INFO : Using log scale\n");
- 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;
+ /*-------------------------------------------------------------------*/
- default: /* Linear scale (min-max) */
+ /* IF user has provided a range, fix them as min & max in image */
+ if (usrclip == 1)
+ {
+ printinfo("user defined pixel range");
for (i = 0; i < npixels; ++i)
- image_buffer[i] = (int)(data[i]);
- break;
+ {
+ if (data[i] > datamax) data[i] = datamax;
+ if (data[i] < datamin) data[i] = datamin;
+ } /*endfor*/
}
- /* initialize image histogram. ensure all are zeroes in hist[] */
- for (i = 0; i <= JMAXVAL; ++i) hist[i] = 0;
+ scale_pixels(scale, npixels, data, &image_buffer);
- /* construct the image histogram */
- tmp = 1.0/(float)npixels;
- for (i = 0; i <= npixels; ++i)
- hist[(int)floor(data[i])] += tmp;
-
- /* And the cumulative histogram */
- cumhist[0] = hist[0];
- for (i = 1; i <= JMAXVAL; ++i)
- cumhist[i] += cumhist[i - 1] + hist[i];
-
- switch (process)
+ /* Before we write jpeg, check if there is any requirement to negate
+ * the image (usrnegt = 1) */
+ if (usrnegt == 1)
{
- case 1 : /* contrast stretch */
- printf("INFO : Performing contrast stretch (normalization) \n");
-
- datamax = (float)JMAXVAL;
- datamin = 0.0;
-
- /* We need to go through the cumulative histogram to pick the
- appropriate values for datamin and datamax */
- i = 0;
- while (i < JMAXVAL)
- {
- if (cumhist[i] >= 0.01)
- {
- datamin = (float) i;
- break;
- }
- i++;
- }
- i = JMAXVAL;
- while (i > 0)
- {
- if (cumhist[i] <= 0.99)
- {
- datamax = (float) i;
- break;
- }
- i--;
- }
- scl_data = (datamax - datamin)/(float)JMAXVAL;
- for (i = 0; i < npixels; ++i)
- {
- if (image_buffer[i] >= datamax)
- image_buffer[i] = JMAXVAL;
- else if (image_buffer[i] <= datamin)
- image_buffer[i] = 0;
- else
- image_buffer[i]=(int)abs((image_buffer[i]-datamin)/scl_data);
- }
- break;
-
+ printinfo("Negating Image");
+ for (i = 0; i < npixels; ++i) image_buffer[i] ^= 0xff;
+ }
- case 2 : /* histogram equalization */
- printf("INFO : Performing Histogram Equalization\n");
- for (i = 0; i < npixels; ++i)
- image_buffer[i] = cumhist[image_buffer[i]]*255;
- break;
+ if (usrzoom == 1)
+ {
+ printf("INFO : Image zoom factor = %3.2f\n", zoomfact);
+ resize_image(&xdim, &ydim, zoomfact, &image_buffer);
}
/*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_file = fopen(jpeg_file_name, "wb");/* Open JPEG file for writing*/
jpeg_stdio_dest(&cinfo, jpeg_file); /* Send compressed data to stdio */
- cinfo.image_width = naxes[0]; /* Image width */
- cinfo.image_height = naxes[1]; /* Image height */
+ cinfo.image_width = xdim; /* Image width */
+ cinfo.image_height = ydim; /* Image height */
cinfo.input_components = 1; /* Number of colors per pixel */
cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
jpeg_set_defaults(&cinfo); /* Set JPEG defaults */
+ jpeg_set_quality(&cinfo, jpgqual, TRUE); /* Set jpeg quality factor */
jpeg_start_compress(&cinfo, TRUE); /* default data compression */
- row_stride = naxes[0]; /* JSAMPLEs per row inimage buffer */
+ row_stride = xdim; /* JSAMPLEs per row inimage buffer */
/* Now we have to turn the data upside down */
while (cinfo.next_scanline < cinfo.image_height)
row_pointer[0] = &image_buffer[(cinfo.image_height -
cinfo.next_scanline) *
row_stride];
+
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}/*Loop through file writing one line at a time*/
diff --git a/src/fits2jpeg.h b/src/fits2jpeg.h
--- /dev/null
+++ b/src/fits2jpeg.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*Header Definitions*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <ctype.h>
+#include <math.h>
+#include <errno.h>
+#include <libgen.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fitsio2.h>
+#include <jpeglib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define PROGRAM "fits2jpeg"
+#define r2d (90./atan2(1,0))
+#define MAX_TEXT 1024
+
+int my_getopt(int, char * const *, const char *);
+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
--- /dev/null
+++ b/src/image.c
@@ -0,0 +1,252 @@
+/***************************************************************************
+ * 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"
+
+/*---------------------------------------------------------------------------*
+ * READ_FITS: To reads data from a fits image file.. (isn't that obvious?)
+ *---------------------------------------------------------------------------*/
+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..
+ *---------------------------------------------------------------------------*/
+void scale_pixels(int scale, unsigned int npixels, float *data,
+ JSAMPLE ** image_buffer)
+{
+ unsigned int i = 0;
+ int JMAXVAL = 255;
+ float datamax = 0.0, datamin = 0.0, tmp = 0.0;
+ float hist[256] = {0.0}, cumhist[256] = {0.0};
+ float scl_data = 0.0;
+
+
+ /* first find min & max in data */
+ datamax = -1.0 * FLT_MAX;
+ datamin = FLT_MAX;
+ for (i = 0; i < npixels; ++i)
+ {
+ if (data[i] > datamax) datamax = data[i];
+ if (data[i] < datamin) datamin = data[i];
+ } /*endfor*/
+
+
+ /* Convert data into bytscaled values for jpeg file */
+ /* the dynamic range is reduced to 255 for jpeg */
+ scl_data = (datamax - datamin)/(float)JMAXVAL;
+
+ for (i = 0; i < npixels; ++i)
+ data[i] = (data[i] - datamin)/scl_data;
+
+
+ /* All data is now squeezed into the range 0 - 255 */
+ /* NOTE: At this point onwards min & max is 0 and 255 respectively */
+ datamax = (float)JMAXVAL;
+ datamin = 0.0;
+
+ /* initialize image histogram. ensure all are zeroes in hist[] */
+ /*-----------------------------------------------------------------------*/
+ for (i = 0; i <= JMAXVAL; ++i) hist[i] = 0;
+
+ /* construct the image histogram */
+ tmp = 1.0/(float)npixels;
+ for (i = 0; i <= npixels; ++i)
+ hist[(int)floor(data[i])] += tmp;
+
+ /* And the cumulative histogram */
+ cumhist[0] = hist[0];
+ for (i = 1; i <= JMAXVAL; ++i)
+ cumhist[i] += cumhist[i - 1] + hist[i];
+
+ /* Allocate image buffer */
+ (*image_buffer) = malloc(sizeof(unsigned char) * npixels);
+
+
+ /* Linear scale (min-max) : This is the default scaling
+ * histo-eq will fail if we dont generate image_buffer here */
+ for (i = 0; i < npixels; ++i)
+ (*image_buffer)[i] = (int)(data[i]);
+
+ /*-----------------------------------------------------------------------*/
+
+
+ switch (scale)
+ {
+ case 1 : /* Square root */
+ 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 */
+ 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 */
+ 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 */
+ 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 */
+ /* We need to go through the cumulative histogram to pick the
+ * appropriate values for datamin and datamax */
+ i = 0;
+ while (i < JMAXVAL)
+ {
+ if (cumhist[i] >= 0.01)
+ {
+ datamin = (float) i;
+ break;
+ }
+ i++;
+ }
+ i = JMAXVAL;
+ while (i > 0)
+ {
+ if (cumhist[i] <= 0.99)
+ {
+ datamax = (float) i;
+ break;
+ }
+ i--;
+ }
+ scl_data = (datamax - datamin)/(float)JMAXVAL;
+ for (i = 0; i < npixels; ++i)
+ {
+ if ((*image_buffer)[i] >= datamax)
+ (*image_buffer)[i] = JMAXVAL;
+ else if ((*image_buffer)[i] <= datamin)
+ (*image_buffer)[i] = 0;
+ else
+ (*image_buffer)[i] = (int) abs(((*image_buffer)[i]
+ - datamin)/scl_data);
+ }
+ break;
+
+ case 6 : /* histogram equalization */
+ for (i = 0; i < npixels; ++i)
+ (*image_buffer)[i] = cumhist[(*image_buffer)[i]] * JMAXVAL;
+ break;
+ default :
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * RESIZE_IMAGE: Scales down/up the image_buffer using bilinear scaling
+ * Based on an article by "John" at
+ * http://tech-algorithm.com/articles/bilinear-image-scaling/
+ *---------------------------------------------------------------------------*/
+void resize_image(long *xdim, long *ydim, float zoomfact,
+ JSAMPLE ** image_buffer)
+{
+ int offset = 0, index = 0;
+ int A, B, C, D, x, y, gray;
+ JSAMPLE *buff;
+ unsigned int i = 0, j = 0;
+ unsigned long npixels = 0;
+ long w = *xdim, h = *ydim;
+ long zxdim = 0, zydim = 0;
+ float xdiff, ydiff, xratio, yratio;
+
+ zxdim = (int)(w * zoomfact);
+ zydim = (int)(h * zoomfact);
+
+ npixels= zxdim * zydim;
+
+ xratio = ((float)(w - 1))/zxdim;
+ yratio = ((float)(h - 1))/zydim;
+
+ /* allocate space for *buff */
+ buff = malloc(sizeof(unsigned char) * zxdim * zydim);
+
+ index = 0;
+ offset = 0;
+ for (i = 0; i < zydim; i++)
+ {
+ y = (int)(yratio * i);
+ ydiff = (yratio * i) - y;
+
+ for (j = 0; j < zxdim; j++)
+ {
+ x = (int)(xratio * j);
+
+ xdiff = (xratio * j) - x;
+ index = y * w + x;
+
+ A = (*image_buffer)[index] & 0xff;
+ B = (*image_buffer)[index + 1] & 0xff;
+ C = (*image_buffer)[index + w] & 0xff;
+ D = (*image_buffer)[index + w + 1] & 0xff;
+
+ gray = (int)(A * (1 - xdiff) * (1 - ydiff)
+ + B * (xdiff) * (1 - ydiff)
+ + C * (ydiff) * (1 - xdiff)
+ + D * (xdiff) * (ydiff)
+ );
+ buff[offset++] = gray;
+ }
+ }
+ *xdim = zxdim;
+ *ydim = zydim;
+ (*image_buffer) = realloc((*image_buffer), sizeof(unsigned char) * npixels);
+ for (i = 0; i < npixels; ++i)
+ (*image_buffer)[i] = buff[i];
+ free(buff);
+}
diff --git a/src/messages.c b/src/messages.c
--- /dev/null
+++ b/src/messages.c
@@ -0,0 +1,99 @@
+/***************************************************************************
+ * 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"
+
+/*---------------------------------------------------------------------------*/
+void banner()
+{
+ printf("\n");
+ printf(" %s %s\n", PROGRAM, VERSION);
+ printf(" Converts fits image files to jpeg\n");
+ printf("-----------------------------------------------------------\n");
+}
+/*---------------------------------------------------------------------------*/
+void usage()
+{
+ printf ("\n Usage: fits2jpeg [options] <fits_file>\n");
+ printf (" Name of fits image file <fits_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 <scale_type> \n");
+ printf (" scale for output image, where <scale_type> can be: \n");
+ printf (" linear Linear scale, default \n");
+ printf (" sqroot for square root scale \n");
+ printf (" square for quadratic scale \n");
+ 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\n");
+ printf (" -n \n");
+ printf (" Negate the image \n\n");
+ printf (" -q <value> \n");
+ printf (" quality factor. Defines the jpeg encoding quality \n");
+ printf (" Valid range: 0-100, default value: 100 (max.quality)\n\n");
+ printf (" -d <path/to/output/directory> \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 <min>:<max> \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\n");
+ printf (" -z <zoomfactor> \n");
+ printf (" Resize/Scale output image by <zoomfactor>. 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\n");
+ printf (" Output will be written to <fits_file_root>.jpg. Wild card\n");
+ printf (" entries allowed in <fits_file>; For eg: *.fits, m31*.fits\n");
+ printf (" ngc???.fits etc. \n");
+ printf ("-----------------------------------------------------------\n");
+ printf ("Copyright (c) 2012 The CADS Team, IIAp. [GPL v3.0 or later]\n");
+ printf ("Report Bugs to: http://cads.iiap.res.in/bugzilla \n");
+ printf ("Documentation : http://cads.iiap.res.in/software \n\n");
+ exit(1);
+}
+
+void printinfo(const char * msg)
+{
+ fprintf(stdout, "INFO : %s\n", msg);
+}
+
+void printwarn(const char * msg)
+{
+ fprintf(stdout, "WARNING: %s\n", msg);
+}
+
+void printerro(const char * msg)
+{
+ fprintf(stderr, "ERROR : %s\n", msg);
+ exit(EXIT_FAILURE);
+}
+