diff --git a/src/image.c b/src/image.c
new file mode 100644 (file)
index 0000000..a47b9b7
--- /dev/null
@@ -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);
+}