X-Git-Url: https://cads.iiap.res.in/gitview/?p=fits2jpeg.git;a=blobdiff_plain;f=src%2Fimage.c;fp=src%2Fimage.c;h=a47b9b7555fbe782570c97c07e0d4365997a7275;hp=0000000000000000000000000000000000000000;hb=43cf6bddbf02b21c68b405e267605b1b64cddd8d;hpb=e9b7faa7d8a84a6a7f0e1b65c8859b7405568890 diff --git a/src/image.c b/src/image.c new file mode 100644 index 0000000..a47b9b7 --- /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); +}