cc97e082fdaf86914956d97400bec9431cf7ad82
1 /***************************************************************************
2 * Copyright (C) 2012 by CADS/UV Software Team, *
3 * Indian Institute of Astrophysics *
4 * Bangalore 560034 *
5 * cads_AT_iiap.res.in *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 /*---------------------------------------------------------------------------
23 This program will write out FITS data into a jpeg file.
24 Assume that data are in first extension and are two dimensional
26 Libraries needed are CFITSIO, JPEG
27 Original author: Jayant Murthy
28 Last Modification: 11/05/02
30 Reconstruction and additional features: Reks
31 *---------------------------------------------------------------------------*/
33 /*---------------------------------------------------------------------------
34 Modification History
36 Reks, 5th October 2007: v0.01
37 1. configure checks for jpeglib.
38 optional extra arguments --with-jpeglib=<location>
39 --with-cfitsio=<location>
40 2. Makes blank images! datamin and max are not set..
42 Reks, 6th October 2007: v0.10
43 1. Added 2 functions to fetch max and min from image
44 2. user can choose various scales like log/square/square-root
45 3. Increased verbosity, added banner, help message, etc
46 4. Inputs through getopt. will Ask if mandatory input (fits file) is not
47 provided.
48 5. fitsio2
50 Reks, 10th October 2007: v0.9.0 (close to 1.0)
51 1. Found our niche :-) Can handle wild cards at command line,
52 batch processing.
53 2. Now users cannot specify the output file name though.. Its fixed to
54 <input_file_root>.jpg.
55 3. No getopt for input file.. getopt is limited to various image scaling
56 options.
58 Reks, 17th October 2007, v0.9.5
59 1. Merged all image scaling options into one input param: -s
60 optarg (from getopt) will decide scaling function. Now there is
61 enough room for additional flags (in future).
63 Reks, 22 June 2010 v1.0.0
64 1. Removed datamax() and datamin(). That was required only once!
65 2. option histoeq shifted to image enhancement option
66 3. Added "normalize" option
67 Now users can do scaling + enhance (if at all someone feels like it)
68 4. All options tested. First stable release :)
70 Reks 28 June 2012
71 1. rebranded to CADS/UVS
73 Reks 05-10 July 2012 v2.0 plans
74 1. Merged scale & operations to single flag
75 2. added fits2jpeg.h, help/banner functions moved to messages.c
76 3. Options to clip image min/max
77 4. negate image option
78 5. jpeg quality factor
79 6. pixel scaling operations moved to image.c
80 7. Image resizing
81 TODO
82 1. move fits read to image.c
83 2. specify output directory
84 *---------------------------------------------------------------------------*/
86 #include "fits2jpeg.h"
88 char *optarg;
89 int optindex;
91 /*--------------------------- Begin Main Progam -----------------------------*/
92 int main(int argc, char *argv[], char *envp[])
93 {
94 fitsfile *fptr;
96 int scale = 0, status = 0, jpgqual = 100, nfound, anynull;
97 unsigned int i = 0, j = 0, usrclip = 0, usrnegt = 0, usrzoom = 0;
98 long xdim = 0, ydim = 0, naxes[2], row_stride;
99 unsigned long npixels = 0;
100 float datamin = 0.0, datamax = 0.0, nullval = 0.0, zoomfact = 1.0;
101 float *data;
102 char jpeg_file_name[MAX_TEXT] = "", fits_file_name[MAX_TEXT] = "";
103 char *tmpstr, *sptr;
105 int opt; /* For getopt */
106 extern char *optarg;
107 extern int optindex;
109 FILE *jpeg_file;
111 struct jpeg_error_mgr jerr;
112 struct jpeg_compress_struct cinfo;
113 JSAMPROW row_pointer[1];
114 JSAMPLE *image_buffer;
115 /*---------------- End of variable initialization -----------------------*/
117 PRINT_BANNER(); /* Header: Talks about program, version & purpose */
118 set_signals(); /* Trap un-natural exits */
120 /*-------------------- Parse command line inputs ------------------------*/
122 if (argc < 2) usage(); /* People who don't give any arguments need help */
123 while ( ( opt = my_getopt ( argc, argv, "e:hnq:r:s:z:" ) ) != EOF )
124 switch ( opt )
125 {
126 case 's':
127 if (strcmp(optarg, "linear") ==0) scale = 0;
128 else if (strcmp(optarg, "sqroot") ==0) scale = 1;
129 else if (strcmp(optarg, "square") ==0) scale = 2;
130 else if (strcmp(optarg, "cubic") ==0) scale = 3;
131 else if (strcmp(optarg, "log") ==0) scale = 4;
132 else if (strcmp(optarg, "normalize")==0) scale = 5;
133 else if (strcmp(optarg, "equalize") ==0) scale = 6;
134 else
135 printwarn(strcat(optarg, " -- Unrecognized option"));
136 scale = 0;
137 break;
139 case 'e':
140 /* Need to preserve it for backward compatibility */
141 if (strcmp(optarg, "normalize")==0) scale = 5;
142 else if (strcmp(optarg, "equalize") ==0) scale = 6;
143 else
144 printerro(strcat(optarg, " -- Unrecognized option"));
145 break;
147 case 'r':
148 tmpstr = optarg; /* make a copy.. and leave optarg alone */
149 sptr = strpbrk(tmpstr, ":"); /* Find the delimiter */
150 if (sptr == NULL)
151 printerro("Expected a ':' as separator for min/max");
153 if (sptr+1 == tmpstr + strlen(tmpstr)) /* -c <datamin>: */
154 datamax = FLT_MAX;
155 else
156 datamax = atof(sptr+1);
158 /* There should be an easier way to find datamin alongside datamax,
159 * but I am too sleepy to try anything now */
160 sptr = strchr(tmpstr, ':');
161 if (sptr == tmpstr) /* -c :<datamax> */
162 datamin = -1.0*FLT_MAX;
163 else
164 {
165 sptr = strtok(tmpstr, ":");
166 datamin = atof(sptr);
167 }
169 /* Remember.. now we have user specified range */
170 usrclip = 1;
171 break;
173 case 'n' :
174 usrnegt = 1;
175 break;
177 case 'q' :
178 jpgqual = atoi(optarg);
179 if (jpgqual < 0) jpgqual = 0;
180 if (jpgqual > 100) jpgqual = 100;
181 printf("INFO : jpeg quality factor changed to %d\n", jpgqual);
182 break;
184 case 'z' :
186 /* Do something to scale image
187 */
188 zoomfact = atof(optarg);
189 zoomfact = abs(zoomfact);
190 if (zoomfact < 0.01) zoomfact = 0.01;
191 if (zoomfact > 4.0) zoomfact = 4.0;
192 usrzoom = 1;
193 break;
195 case 'h':
196 usage();
197 break;
199 default :
200 printerro("You can try 'fits2jpeg -h' for valid options");
201 break;
202 }
204 if ((argc - optindex) == 0) usage(); /* Someone gave only options */
206 /*---------------------- Begin processing files -------------------------*/
208 /* Getopt would have processed all argument with a "-" in front. optindex
209 is the counter, which keeps the number of options supplied. Whatever
210 remains in the list of command line arguments are the fits files.
211 NOTE: POSIX systems will do the regex matching and expand wild card
212 entries for us. Even windoze XP Pro is known to do that... */
213 for (j = optindex; j < argc; j++)
214 {
216 strcpy(fits_file_name, argv[j]);
218 strcpy(jpeg_file_name, fits_file_name);
219 strtok(jpeg_file_name, ".");
220 strcat(jpeg_file_name, ".jpg");
222 fits_open_file(&fptr, fits_file_name, READONLY, &status);
223 fits_read_keys_lng(fptr, "NAXIS", 1, 2, naxes, &nfound, &status);
224 if (status)
225 printerro(strcat(fits_file_name, " <-- Failed to open the file"));
227 /* Read in data */
228 npixels = naxes[0] * naxes[1];
229 data = malloc(sizeof(float) * npixels);
231 nullval = 0;
232 if (fits_read_img(fptr, TFLOAT, 1, npixels, &nullval, data, &anynull,
233 &status))
234 printerro(strcat(fits_file_name, " has no valid fits image data"));
236 fits_close_file(fptr, &status);
237 /*Close data file*/
238 printf("INFO : data input from %s\n", fits_file_name);
241 /* Now we need to look at user options.. */
242 /*-------------------------------------------------------------------*/
244 /* IF user has provided a range, fix them as min & max in image */
245 if (usrclip == 1)
246 {
247 printinfo("user defined pixel range");
248 for (i = 0; i < npixels; ++i)
249 {
250 if (data[i] > datamax) data[i] = datamax;
251 if (data[i] < datamin) data[i] = datamin;
252 } /*endfor*/
253 }
255 scale_pixels(scale, npixels, data, &image_buffer);
257 /* Before we write jpeg, check if there is any requirement to negate
258 * the image (usrnegt = 1) */
259 if (usrnegt == 1)
260 {
261 printinfo("Negating Image");
262 for (i = 0; i < npixels; ++i) image_buffer[i] ^= 0xff;
263 }
265 xdim = naxes[0];
266 ydim = naxes[1];
267 if (usrzoom == 1)
268 {
269 printf("INFO : Image zoom factor = %3.2f\n", zoomfact);
270 resize_image(&xdim, &ydim, zoomfact, &image_buffer);
271 }
273 /*Write out data into JPEG file*/
274 jpeg_file = fopen(jpeg_file_name, "wb");/* Open JPEG file for writing*/
275 cinfo.err = jpeg_std_error(&jerr); /* JPEG error handler */
276 jpeg_create_compress(&cinfo); /* JPEG initialization */
277 jpeg_stdio_dest(&cinfo, jpeg_file); /* Send compressed data to stdio */
278 cinfo.image_width = xdim; /* Image width */
279 cinfo.image_height = ydim; /* Image height */
280 cinfo.input_components = 1; /* Number of colors per pixel */
281 cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
282 jpeg_set_defaults(&cinfo); /* Set JPEG defaults */
283 jpeg_set_quality(&cinfo, jpgqual, TRUE); /* Set jpeg quality factor */
284 jpeg_start_compress(&cinfo, TRUE); /* default data compression */
285 row_stride = xdim; /* JSAMPLEs per row inimage buffer */
287 /* Now we have to turn the data upside down */
288 while (cinfo.next_scanline < cinfo.image_height)
289 {
290 row_pointer[0] = &image_buffer[(cinfo.image_height -
291 cinfo.next_scanline) *
292 row_stride];
294 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
295 }/*Loop through file writing one line at a time*/
297 jpeg_finish_compress(&cinfo); /* Finish compression */
298 fclose(jpeg_file); /* Close file */
299 jpeg_destroy_compress(&cinfo); /* Release memory */
301 free(data);
302 free(image_buffer);
303 printf("INFO : wrote output to %s\n", jpeg_file_name);
304 }
305 exit(EXIT_SUCCESS);
306 } /*End of program*/