60420e2ff4b747eab5de0a89acaf84f7fa88cd3c
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 works for reducing size. segfaults for zoom > 1 :(
81 TODO
82 1. move fits read to image.c
83 2. specify output directory
84 3. Image resizing options
85 *---------------------------------------------------------------------------*/
87 #include "fits2jpeg.h"
89 char *optarg;
90 int optindex;
92 /*--------------------------- Begin Main Progam -----------------------------*/
93 int main(int argc, char *argv[], char *envp[])
94 {
95 fitsfile *fptr;
97 int scale = 0, process = 0, status = 0, jpgqual = 100, nfound, anynull;
98 unsigned int i = 0, j = 0, usrclip = 0, usrnegt = 0, usrzoom = 0;
99 long xdim = 0, ydim = 0, naxes[2], row_stride;
100 unsigned long npixels = 0;
101 float datamin = 0.0, datamax = 0.0, nullval = 0.0, zoomfact = 1.0;
102 float *data;
103 char jpeg_file_name[MAX_TEXT] = "", fits_file_name[MAX_TEXT] = "";
104 char *tmpstr, *sptr;
106 int opt; /* For getopt */
107 extern char *optarg;
108 extern int optindex;
110 FILE *jpeg_file;
112 struct jpeg_error_mgr jerr;
113 struct jpeg_compress_struct cinfo;
114 JSAMPROW row_pointer[1];
115 JSAMPLE *image_buffer;
116 /*---------------- End of variable initialization -----------------------*/
118 PRINT_BANNER(); /* Header: Talks about program, version & purpose */
119 set_signals(); /* Trap un-natural exits */
121 /*-------------------- Parse command line inputs ------------------------*/
123 if (argc < 2) usage(); /* People who don't give any arguments need help */
124 while ( ( opt = my_getopt ( argc, argv, "e:hnq:r:s:z:" ) ) != EOF )
125 switch ( opt )
126 {
127 case 's':
128 if (strcmp(optarg, "linear") ==0) scale = 0;
129 else if (strcmp(optarg, "sqroot") ==0) scale = 1;
130 else if (strcmp(optarg, "square") ==0) scale = 2;
131 else if (strcmp(optarg, "cubic") ==0) scale = 3;
132 else if (strcmp(optarg, "log") ==0) scale = 4;
133 else if (strcmp(optarg, "normalize")==0) scale = 5;
134 else if (strcmp(optarg, "equalize") ==0) scale = 6;
135 else
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 }
168 printinfo("User defined pixel range");
170 /* Remember.. now we have user specified range */
171 usrclip = 1;
172 break;
174 case 'n' :
175 usrnegt = 1;
176 break;
178 case 'q' :
179 jpgqual = atoi(optarg);
180 if (jpgqual < 0) jpgqual = 0;
181 if (jpgqual > 100) jpgqual = 100;
182 printf("INFO : jpeg quality factor changed to %d\n", jpgqual);
183 break;
185 case 'z' :
187 /* Do something to scale image
188 */
189 zoomfact = atof(optarg);
190 if (zoomfact < 0.0) zoomfact = 1.0;
191 usrzoom = 1;
192 break;
194 case 'h':
195 usage();
196 break;
198 default :
199 printerro("You can try 'fits2jpeg -h' for valid options");
200 break;
201 }
203 if ((argc - optindex) == 0) usage(); /* Someone gave only options */
205 /*---------------------- Begin processing files -------------------------*/
207 /* Getopt would have processed all argument with a "-" in front. optindex
208 is the counter, which keeps the number of options supplied. Whatever
209 remains in the list of command line arguments are the fits files.
210 NOTE: POSIX systems will do the regex matching and expand wild card
211 entries for us. Even windoze XP Pro is known to do that... */
212 for (j = optindex; j < argc; j++)
213 {
215 strcpy(fits_file_name, argv[j]);
217 strcpy(jpeg_file_name, fits_file_name);
218 strtok(jpeg_file_name, ".");
219 strcat(jpeg_file_name, ".jpg");
221 fits_open_file(&fptr, fits_file_name, READONLY, &status);
222 fits_read_keys_lng(fptr, "NAXIS", 1, 2, naxes, &nfound, &status);
223 if (status)
224 printerro(strcat(fits_file_name, " <-- Failed to open the file"));
226 /* Read in data */
227 npixels = naxes[0] * naxes[1];
228 data = (float *) malloc(sizeof(float) * npixels);
230 nullval = 0;
231 if (fits_read_img(fptr, TFLOAT, 1, npixels, &nullval, data, &anynull,
232 &status))
233 printerro(strcat(fits_file_name, " has no valid fits image data"));
235 fits_close_file(fptr, &status);
236 /*Close data file*/
237 printf("INFO : data input from %s\n", fits_file_name);
240 /* Now we need to look at user options.. */
241 /*-------------------------------------------------------------------*/
243 /* IF user has provided a range, fix them as min & max in image */
244 if (usrclip == 1)
245 {
246 for (i = 0; i < npixels; ++i)
247 {
248 if (data[i] > datamax) data[i] = datamax;
249 if (data[i] < datamin) data[i] = datamin;
250 } /*endfor*/
251 }
253 /* Allocate image buffer */
254 image_buffer = (unsigned char *) malloc(sizeof(char) * npixels);
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) resize_image(&xdim, &ydim, zoomfact, image_buffer);
269 /*Write out data into JPEG file*/
270 jpeg_file = fopen(jpeg_file_name, "wb");/* Open JPEG file for writing*/
271 cinfo.err = jpeg_std_error(&jerr); /* JPEG error handler */
272 jpeg_create_compress(&cinfo); /* JPEG initialization */
273 jpeg_stdio_dest(&cinfo, jpeg_file); /* Send compressed data to stdio */
274 cinfo.image_width = xdim; /* Image width */
275 cinfo.image_height = ydim; /* Image height */
276 cinfo.input_components = 1; /* Number of colors per pixel */
277 cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
278 jpeg_set_defaults(&cinfo); /* Set JPEG defaults */
279 jpeg_set_quality(&cinfo, jpgqual, TRUE); /* Set jpeg quality factor */
280 jpeg_start_compress(&cinfo, TRUE); /* default data compression */
281 row_stride = xdim; /* JSAMPLEs per row inimage buffer */
283 /* Now we have to turn the data upside down */
284 while (cinfo.next_scanline < cinfo.image_height)
285 {
286 row_pointer[0] = &image_buffer[(cinfo.image_height -
287 cinfo.next_scanline) *
288 row_stride];
290 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
291 }/*Loop through file writing one line at a time*/
293 jpeg_finish_compress(&cinfo); /* Finish compression */
294 fclose(jpeg_file); /* Close file */
295 jpeg_destroy_compress(&cinfo); /* Release memory */
297 free(data);
298 free(image_buffer);
299 printf("INFO : wrote output to %s\n", jpeg_file_name);
300 }
301 exit(EXIT_SUCCESS);
302 } /*End of program*/