summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e31da38)
raw | patch | inline | side by side (parent: e31da38)
author | Rekhesh Mohan <reks@iiap.res.in> | |
Wed, 11 Jul 2012 21:54:56 +0000 (03:24 +0530) | ||
committer | Rekhesh Mohan <reks@iiap.res.in> | |
Wed, 11 Jul 2012 21:54:56 +0000 (03:24 +0530) |
README.txt | patch | blob | history | |
configure.ac | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/fits2jpeg.c | patch | blob | history | |
src/fits2jpeg.h | patch | blob | history | |
src/getopt.c | patch | blob | history | |
src/image.c | patch | blob | history | |
src/messages.c | patch | blob | history |
diff --git a/README.txt b/README.txt
--- a/README.txt
+++ b/README.txt
2.USAGE
-------
- fits2jpeg [options] <fits_file>
+ Usage: fits2jpeg [options] <fits_file>
+
+ Options are:
- Options are:
-h help
-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
+ normalize for linear histogram stretch
+ equalize for histogram equalization
+
+ -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
+
+ -n
+ Negate the image.
+
+ -q <value>
+ jpeg quality factor. Defines the jpeg encoding quality
+ Valid range: 0-100, default value: 100, which is for
+ best quality (and largest file size).
- -e <operation>
- Imaghe enhancement operations. Valid arguments are:
+ -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
- equalize perform histogram equalization
- normalize perform a linear contrast stretch
- (use cutoffs at 1% and 99% for image data)
Output will be written to <fits_file_root>.jpg. For eg.,
More examples:
- i. fits2jpeg -s cubic sirius.fits
+ i. fits2jpeg -s log sirius.fits
will write out sirius.jpg, flux/intensity in log scale
ii. fits2jpeg -s sqroot *.fits
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.
+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.
3. DOCUMENTATION
-----------------------------------------------------------
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.90], [cads@iiap.res.in])
+AC_INIT([CADS_fits2jpeg], [1.95], [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([stdio.h stdlib.h string.h math.h float.h ctype.h libgen.h dirent.h])
# Checks for typedefs, structures, and compiler characteristics.
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 messages.c getopt.c image.c signal_handler.c
+noinst_HEADERS = fits2jpeg.h
\ No newline at end of file
diff --git a/src/fits2jpeg.c b/src/fits2jpeg.c
--- a/src/fits2jpeg.c
+++ b/src/fits2jpeg.c
Reconstruction and additional features: Reks
*---------------------------------------------------------------------------*/
+
/*---------------------------------------------------------------------------
Modification History
Reks 28 June 2012
1. rebranded to CADS/UVS
- Reks 05 July 2012 v2.0 plans
+ 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 works for reducing size. segfaults for zoom > 1 :(
TODO
- 1. New option to specify min-max for image
+ 1. move fits read to image.c
2. specify output directory
- 3. output filename for single input file
- 4. Image resizing options
-
- *-------------------------------------------------------------------------*/
-
-#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);
+ 3. Image resizing options
+ *---------------------------------------------------------------------------*/
+
+#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");
- 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");
- 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, process = 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;
+ float datamin = 0.0, datamax = 0.0, nullval = 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 *tmpstr, *sptr;
int opt; /* For getopt */
extern char *optarg;
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 -----------------------*/
/*-------------------- Parse command line inputs ------------------------*/
if (argc < 2) usage(); /* People who don't give any arguments need help */
- while ( ( opt = my_getopt ( argc, argv, "s:r:h" ) ) != EOF )
+ while ( ( opt = my_getopt ( argc, argv, "e:hnq:r:s:z:" ) ) != EOF )
switch ( opt )
{
case 's':
- if (strcmp(optarg, "sqroot") ==0) scale = 1;
+ 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, "cube") ==0) scale = 3;
+ 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;
else
+ 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;
+ 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
{
- fprintf(stderr, "ERROR : Unrecognized option : %s\n", optarg);
- exit(EXIT_FAILURE);
+ sptr = strtok(tmpstr, ":");
+ datamin = atof(sptr);
}
+ printinfo("User defined pixel range");
+
+ /* Remember.. now we have user specified range */
+ usrclip = 1;
break;
- case 'r':
- /*
- * read a string like <min>:<max>
- * set a flag. If this flag is on, do a 'reverse map'
- * instead of search for datamin & datamax
+ 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' :
+
+ /* Do something to scale image
*/
+ zoomfact = atof(optarg);
+ if (zoomfact < 0.0) zoomfact = 1.0;
+ usrzoom = 1;
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 ((argc - optindex) == 0) usage(); /* Someone gave only options */
/*---------------------- Begin processing files -------------------------*/
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*/
+ printerro(strcat(fits_file_name, " <-- Failed to open the file"));
/* Read in data */
npixels = naxes[0] * naxes[1];
nullval = 0;
if (fits_read_img(fptr, TFLOAT, 1, npixels, &nullval, data, &anynull,
&status))
- {
- fprintf(stderr, "ERROR : No valid fits image data in %s\n",
- fits_file_name);
- exit(EXIT_FAILURE);
- }/*Endif*/
+ printerro(strcat(fits_file_name, " has no valid fits image data"));
fits_close_file(fptr, &status);
/*Close data file*/
printf("INFO : data input from %s\n", fits_file_name);
- /* IF no range is provided, 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*/
-
-
- /* 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 */
-
/* 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;
-
-
- /* 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];
- /*-------------------------------------------------------------------*/
-
-
- switch (scale)
+ /* IF user has provided a range, fix them as min & max in image */
+ if (usrclip == 1)
{
- 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;
-
- case 5 :
- /* contrast stretch */
- printf("INFO : Performing histogram 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;
+ if (data[i] > datamax) data[i] = datamax;
+ if (data[i] < datamin) data[i] = datamin;
+ } /*endfor*/
+ }
- case 6 :
- /* histogram equalization */
- printf("INFO : Performing Histogram Equalization\n");
- for (i = 0; i < npixels; ++i)
- image_buffer[i] = cumhist[image_buffer[i]]*255;
- break;
+ /* Allocate image buffer */
+ image_buffer = (unsigned char *) malloc(sizeof(char) * npixels);
+ scale_pixels(scale, npixels, data, image_buffer);
- default: /* Linear scale (min-max) */
- for (i = 0; i < npixels; ++i)
- image_buffer[i] = (int)(data[i]);
- break;
+ /* Before we write jpeg, check if there is any requirement to negate
+ * the image (usrnegt = 1) */
+ if (usrnegt == 1)
+ {
+ printinfo("Negating Image");
+ for (i = 0; i < npixels; ++i) image_buffer[i] ^= 0xff;
}
+ xdim = naxes[0];
+ ydim = naxes[1];
+ if (usrzoom == 1) 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*/
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
--- a/src/fits2jpeg.h
+++ b/src/fits2jpeg.h
void printinfo(const char *);
void printwarn(const char *);
void printerro(const char *);
-void scale_image(int, int, float *, JSAMPLE *);
+void scale_pixels(int, unsigned int, float *, JSAMPLE *);
+void resize_image(long *, long *, float, JSAMPLE *);
diff --git a/src/getopt.c b/src/getopt.c
--- a/src/getopt.c
+++ b/src/getopt.c
(void)fprintf(stderr,
"ERROR : option requires an argument -- %c\n",
optopt);
- return (BADCH);
+ exit (BADCH);
}
else /* white space */
optarg = nargv[optindex];
diff --git a/src/image.c b/src/image.c
--- a/src/image.c
+++ b/src/image.c
/*Header Definitions*/
#include "fits2jpeg.h"
-void scale_image(int scale, int npixels,
+/*---------------------------------------------------------------------------*
+ * 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;
float scl_data = 0.0;
- /* first find min & max in data */
+ /* first find min & max in data */
datamax = -1.0 * FLT_MAX;
datamin = FLT_MAX;
for (i = 0; i < npixels; ++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 */
+
+ /* 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 */
+
+ /* 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[] */
- /*-------------------------------------------------------------------*/
+ /* initialize image histogram. ensure all are zeroes in hist[] */
+ /*-----------------------------------------------------------------------*/
for (i = 0; i <= JMAXVAL; ++i) hist[i] = 0;
/* construct the image histogram */
cumhist[i] += cumhist[i - 1] + hist[i];
/* Linear scale (min-max) : This is the default scaling
- * if we dont generate image_buffer here, histo-eq will fail */
+ * 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)
else if (image_buffer[i] <= datamin)
image_buffer[i] = 0;
else
- image_buffer[i] = (int) abs((image_buffer[i] - datamin)/scl_data);
+ image_buffer[i] = (int) abs((image_buffer[i]
+ - datamin)/scl_data);
}
break;
/* histogram equalization */
printinfo("Performing Histogram Equalization");
for (i = 0; i < npixels; ++i)
- image_buffer[i] = cumhist[image_buffer[i]] * 255;
+ image_buffer[i] = cumhist[image_buffer[i]] * JMAXVAL;
break;
default :
printinfo("Using linear scale");
}
}
+
+/*---------------------------------------------------------------------------*
+ * RESIZE_IMAGE: Scales down/up the 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;
+ 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 = (unsigned char *) malloc(sizeof(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(char) * npixels);
+ if (!image_buffer)
+ printerro("Failed to allocate memory");
+
+ for (i = 0; i < npixels; ++i)
+ image_buffer[i] = buff[i];
+}
diff --git a/src/messages.c b/src/messages.c
--- a/src/messages.c
+++ b/src/messages.c
printf (" log for log scale \n");
printf (" normalize for linear histogram stretch \n");
printf (" equalize for histogram equalization \n");
- printf (" -c <min>:<max> \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 below 10 \n");
printf (" -n \n");
printf (" Negate the image \n");
- printf (" -q \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");
printf (" -z <zoomfactor> \n");