From c217f20a424f31d11946263980a8f14ca7a79a0e Mon Sep 17 00:00:00 2001 From: Rekhesh Mohan Date: Thu, 12 Jul 2012 16:54:30 +0530 Subject: [PATCH] Fixed image zoom/scale option --- .gitignore | 1 + ChangeLog.txt | 28 ++++++++++++++++++++++++- README.txt | 63 ++++++++++++++++++++++++++++++++++----------------------- configure.ac | 5 +++-- src/fits2jpeg.c | 24 +++++++++++++--------- src/fits2jpeg.h | 8 +++++--- src/image.c | 58 +++++++++++++++++++++++++++------------------------- src/messages.c | 3 +++ 8 files changed, 122 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index 3820d63..40495b4 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,6 @@ src/*.o stamp-h1 *~ .*.swp +.*swp *.bak *.lock diff --git a/ChangeLog.txt b/ChangeLog.txt index e557841..4076135 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -3,5 +3,31 @@ CHANGELOG for CADS/UVS fits2jpeg software ------------------------------------------------------------------------ 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 using "-z ". + + 5. New option to choose jpeg quality factor + You can choose the jpeg quality factor using "-q " + Quality factor was fixed at 100 in previous release. + diff --git a/README.txt b/README.txt index df79f4a..c5f5ca1 100644 --- a/README.txt +++ b/README.txt @@ -6,12 +6,11 @@ README file for CADS/UVS fits2jpeg software 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 @@ -26,9 +25,10 @@ Pre-requisites: 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: @@ -61,20 +61,19 @@ Pre-requisites: 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 @@ -116,6 +115,9 @@ file named `INSTALL.txt'. 0.5 Shrink output to half of input 2.0 Magnify output to double the size + 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 Output will be written to .jpg. For eg., @@ -123,8 +125,8 @@ file named `INSTALL.txt'. writes output to jpeg file 30dor.jpg - Wild card entries allowed in . For eg: *.fits, - m31*.fits ngc???.fits etc. + Wild card entries allowed in . For eg: *.fits, m31*.fits + ngc???.fits etc. More examples: @@ -145,11 +147,22 @@ iv. fits2jpeg -s square -n -r 10:2000 m31.fits units. +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] @@ -158,10 +171,9 @@ in the user manual, which is yet to be written :( 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 @@ -174,6 +186,7 @@ If you are too lazy, drop in an email to: cads_AT_iiap.res.in Either way, please include as many details as possible. + ----------------------------------------------------------- Reks, 28 June 2012 Last modified: 10 July 2012 diff --git a/configure.ac b/configure.ac index dd6b85e..770550d 100644 --- a/configure.ac +++ b/configure.ac @@ -13,15 +13,16 @@ AC_PROG_MAKE_SET # Checks for libraries. # Checks for header files. -AC_CHECK_HEADERS([stdio.h stdlib.h 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]) # 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/fits2jpeg.c b/src/fits2jpeg.c index 60420e2..cc97e08 100644 --- a/src/fits2jpeg.c +++ b/src/fits2jpeg.c @@ -77,11 +77,10 @@ 4. negate image option 5. jpeg quality factor 6. pixel scaling operations moved to image.c - 7. Image resizing works for reducing size. segfaults for zoom > 1 :( + 7. Image resizing TODO 1. move fits read to image.c 2. specify output directory - 3. Image resizing options *---------------------------------------------------------------------------*/ #include "fits2jpeg.h" @@ -94,7 +93,7 @@ int main(int argc, char *argv[], char *envp[]) { fitsfile *fptr; - int scale = 0, process = 0, status = 0, jpgqual = 100, nfound, anynull; + 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; unsigned long npixels = 0; @@ -133,6 +132,7 @@ int main(int argc, char *argv[], char *envp[]) else if (strcmp(optarg, "normalize")==0) scale = 5; else if (strcmp(optarg, "equalize") ==0) scale = 6; else + printwarn(strcat(optarg, " -- Unrecognized option")); scale = 0; break; @@ -165,7 +165,6 @@ int main(int argc, char *argv[], char *envp[]) sptr = strtok(tmpstr, ":"); datamin = atof(sptr); } - printinfo("User defined pixel range"); /* Remember.. now we have user specified range */ usrclip = 1; @@ -187,7 +186,9 @@ int main(int argc, char *argv[], char *envp[]) /* Do something to scale image */ zoomfact = atof(optarg); - if (zoomfact < 0.0) zoomfact = 1.0; + zoomfact = abs(zoomfact); + if (zoomfact < 0.01) zoomfact = 0.01; + if (zoomfact > 4.0) zoomfact = 4.0; usrzoom = 1; break; @@ -225,7 +226,7 @@ int main(int argc, char *argv[], char *envp[]) /* Read in data */ npixels = naxes[0] * naxes[1]; - data = (float *) malloc(sizeof(float) * npixels); + data = malloc(sizeof(float) * npixels); nullval = 0; if (fits_read_img(fptr, TFLOAT, 1, npixels, &nullval, data, &anynull, @@ -243,6 +244,7 @@ int main(int argc, char *argv[], char *envp[]) /* 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) { if (data[i] > datamax) data[i] = datamax; @@ -250,9 +252,7 @@ int main(int argc, char *argv[], char *envp[]) } /*endfor*/ } - /* Allocate image buffer */ - image_buffer = (unsigned char *) malloc(sizeof(char) * npixels); - scale_pixels(scale, npixels, data, image_buffer); + scale_pixels(scale, npixels, data, &image_buffer); /* Before we write jpeg, check if there is any requirement to negate * the image (usrnegt = 1) */ @@ -264,7 +264,11 @@ int main(int argc, char *argv[], char *envp[]) xdim = naxes[0]; ydim = naxes[1]; - if (usrzoom == 1) resize_image(&xdim, &ydim, zoomfact, image_buffer); + 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*/ diff --git a/src/fits2jpeg.h b/src/fits2jpeg.h index a96f9fb..3920d82 100644 --- a/src/fits2jpeg.h +++ b/src/fits2jpeg.h @@ -39,13 +39,15 @@ #define PROGRAM "fits2jpeg" #define r2d (90./atan2(1,0)) -#define MAX_TEXT 150 +#define MAX_TEXT 1024 int my_getopt(int, char * const *, const char *); +void PRINT_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 scale_pixels(int, unsigned int, float *, JSAMPLE *); -void resize_image(long *, long *, float, JSAMPLE *); +void scale_pixels(int, unsigned int, float *, JSAMPLE **); +void resize_image(long *, long *, float, JSAMPLE **); diff --git a/src/image.c b/src/image.c index d1c22f0..f5f6c46 100644 --- a/src/image.c +++ b/src/image.c @@ -27,8 +27,8 @@ /*---------------------------------------------------------------------------* * SCALE_PIXELS: Changes the pixel scale to linear/log/sqroot/etc.. *---------------------------------------------------------------------------*/ -void scale_pixels(int scale, unsigned int npixels, - float *data, JSAMPLE *image_buffer) +void scale_pixels(int scale, unsigned int npixels, float *data, + JSAMPLE ** image_buffer) { unsigned int i = 0; int JMAXVAL = 255; @@ -74,10 +74,14 @@ void scale_pixels(int scale, unsigned int npixels, 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]); + (*image_buffer)[i] = (int)(data[i]); /*-----------------------------------------------------------------------*/ @@ -88,28 +92,28 @@ void scale_pixels(int scale, unsigned int npixels, 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); + (*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); + (*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); + (*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); + (*image_buffer)[i] = (int)((log(abs(data[i]) + 1.0))/scl_data); break; case 5 : @@ -141,12 +145,12 @@ void scale_pixels(int scale, unsigned int npixels, 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; + 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] + (*image_buffer)[i] = (int) abs(((*image_buffer)[i] - datamin)/scl_data); } break; @@ -155,19 +159,21 @@ void scale_pixels(int scale, unsigned int npixels, /* histogram equalization */ printinfo("Performing Histogram Equalization"); for (i = 0; i < npixels; ++i) - image_buffer[i] = cumhist[image_buffer[i]] * JMAXVAL; + (*image_buffer)[i] = cumhist[(*image_buffer)[i]] * JMAXVAL; break; default : printinfo("Using linear scale"); break; } - } /*---------------------------------------------------------------------------* - * RESIZE_IMAGE: Scales down/up the image_buffer + * 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) +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; @@ -186,8 +192,8 @@ void resize_image(long *xdim, long *ydim, float zoomfact, JSAMPLE *image_buffer) xratio = ((float)(w - 1))/zxdim; yratio = ((float)(h - 1))/zydim; - /* allocate space for *buff */ - buff = (unsigned char *) malloc(sizeof(char) * zxdim * zydim); + /* allocate space for *buff */ + buff = malloc(sizeof(unsigned char) * zxdim * zydim); index = 0; offset = 0; @@ -203,10 +209,10 @@ void resize_image(long *xdim, long *ydim, float zoomfact, JSAMPLE *image_buffer) 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; + 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) @@ -218,10 +224,8 @@ void resize_image(long *xdim, long *ydim, float zoomfact, JSAMPLE *image_buffer) } *xdim = zxdim; *ydim = zydim; - image_buffer = realloc(image_buffer, sizeof(char) * npixels); - if (!image_buffer) - printerro("Failed to allocate memory"); - + (*image_buffer) = realloc((*image_buffer), sizeof(unsigned char) * npixels); for (i = 0; i < npixels; ++i) - image_buffer[i] = buff[i]; + (*image_buffer)[i] = buff[i]; + free(buff); } diff --git a/src/messages.c b/src/messages.c index edcdc68..75f890c 100644 --- a/src/messages.c +++ b/src/messages.c @@ -62,6 +62,9 @@ void usage() 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 (" 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