1 /*** File imhfile.c
2 *** March 27, 2012
3 *** By Jessica Mink, jmink@cfa.harvard.edu
4 *** Harvard-Smithsonian Center for Astrophysics
5 *** Copyright (C) 1996-2012
6 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 Correspondence concerning WCSTools should be addressed as follows:
23 Internet email: jmink@cfa.harvard.edu
24 Postal address: Jessica Mink
25 Smithsonian Astrophysical Observatory
26 60 Garden St.
27 Cambridge, MA 02138 USA
28
29 * Module: imhfile.c (IRAF .imh image file reading and writing)
30 * Purpose: Read and write IRAF image files (and translate headers)
31 * Subroutine: check_immagic (irafheader, teststring )
32 * Verify that file is valid IRAF imhdr or impix
33 * Subroutine: irafrhead (filename, lfhead, fitsheader, lihead)
34 * Read IRAF image header
35 * Subroutine: irafrimage (fitsheader)
36 * Read IRAF image pixels (call after irafrhead)
37 * Subroutine: same_path (pixname, hdrname)
38 * Put filename and header path together
39 * Subroutine: iraf2fits (hdrname, irafheader, nbiraf, nbfits)
40 * Convert IRAF image header to FITS image header
41 * Subroutine: irafwhead (hdrname, irafheader, fitsheader)
42 * Write IRAF header file
43 * Subroutine: irafwimage (hdrname, irafheader, fitsheader, image )
44 * Write IRAF image and header files
45 * Subroutine: fits2iraf (fitsheader, irafheader)
46 * Convert FITS image header to IRAF image header
47 * Subroutine: irafgeti4 (irafheader, offset)
48 * Get 4-byte integer from arbitrary part of IRAF header
49 * Subroutine: irafgetc2 (irafheader, offset)
50 * Get character string from arbitrary part of IRAF v.1 header
51 * Subroutine: irafgetc (irafheader, offset)
52 * Get character string from arbitrary part of IRAF header
53 * Subroutine: iraf2str (irafstring, nchar)
54 * Convert 2-byte/char IRAF string to 1-byte/char string
55 * Subroutine: str2iraf (string, irafstring, nchar)
56 * Convert 1-byte/char string to IRAF 2-byte/char string
57 * Subroutine: irafswap (bitpix,string,nbytes)
58 * Swap bytes in string in place, with FITS bits/pixel code
59 * Subroutine: irafswap2 (string,nbytes)
60 * Swap bytes in string in place
61 * Subroutine irafswap4 (string,nbytes)
62 * Reverse bytes of Integer*4 or Real*4 vector in place
63 * Subroutine irafswap8 (string,nbytes)
64 * Reverse bytes of Real*8 vector in place
65 * Subroutine irafsize (filename)
66 * Return length of file in bytes
67 * Subroutine isiraf (filename)
68 * Return 1 if IRAF .imh file, else 0
69
70
71 * Copyright: 2000 Smithsonian Astrophysical Observatory
72 * You may do anything you like with this file except remove
73 * this copyright. The Smithsonian Astrophysical Observatory
74 * makes no representations about the suitability of this
75 * software for any purpose. It is provided "as is" without
76 * express or implied warranty.
77 */
78
79 #include <stdio.h> /* define stderr, FD, and NULL */
80 #include <stdlib.h>
81 #include <unistd.h>
82 #include <fcntl.h>
83 #include <string.h>
84 #include <time.h>
85 #include <sys/types.h>
86 #include "fitsfile.h"
87
88 /* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */
89 #define SZ_IMPIXFILE 79 /* name of pixel storage file */
90 #define SZ_IMHDRFILE 79 /* length of header storage file */
91 #define SZ_IMTITLE 79 /* image title string */
92 #define LEN_IMHDR 2052 /* length of std header */
93
94 /* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */
95 #define SZ_IM2PIXFILE 255 /* name of pixel storage file */
96 #define SZ_IM2HDRFILE 255 /* name of header storage file */
97 #define SZ_IM2TITLE 383 /* image title string */
98 #define LEN_IM2HDR 2046 /* length of std header */
99
100 /* Offsets into header in bytes for parameters in IRAF version 1 images */
101 #define IM_HDRLEN 12 /* Length of header in 4-byte ints */
102 #define IM_PIXTYPE 16 /* Datatype of the pixels */
103 #define IM_NDIM 20 /* Number of dimensions */
104 #define IM_LEN 24 /* Length (as stored) */
105 #define IM_PHYSLEN 52 /* Physical length (as stored) */
106 #define IM_PIXOFF 88 /* Offset of the pixels */
107 #define IM_CTIME 108 /* Time of image creation */
108 #define IM_MTIME 112 /* Time of last modification */
109 #define IM_LIMTIME 116 /* Time of min,max computation */
110 #define IM_MAX 120 /* Maximum pixel value */
111 #define IM_MIN 124 /* Maximum pixel value */
112 #define IM_PIXFILE 412 /* Name of pixel storage file */
113 #define IM_HDRFILE 572 /* Name of header storage file */
114 #define IM_TITLE 732 /* Image name string */
115
116 /* Offsets into header in bytes for parameters in IRAF version 2 images */
117 #define IM2_HDRLEN 6 /* Length of header in 4-byte ints */
118 #define IM2_PIXTYPE 10 /* Datatype of the pixels */
119 #define IM2_SWAPPED 14 /* Pixels are byte swapped */
120 #define IM2_NDIM 18 /* Number of dimensions */
121 #define IM2_LEN 22 /* Length (as stored) */
122 #define IM2_PHYSLEN 50 /* Physical length (as stored) */
123 #define IM2_PIXOFF 86 /* Offset of the pixels */
124 #define IM2_CTIME 106 /* Time of image creation */
125 #define IM2_MTIME 110 /* Time of last modification */
126 #define IM2_LIMTIME 114 /* Time of min,max computation */
127 #define IM2_MAX 118 /* Maximum pixel value */
128 #define IM2_MIN 122 /* Maximum pixel value */
129 #define IM2_PIXFILE 126 /* Name of pixel storage file */
130 #define IM2_HDRFILE 382 /* Name of header storage file */
131 #define IM2_TITLE 638 /* Image name string */
132
133 /* Codes from iraf/unix/hlib/iraf.h */
134 #define TY_CHAR 2
135 #define TY_SHORT 3
136 #define TY_INT 4
137 #define TY_LONG 5
138 #define TY_REAL 6
139 #define TY_DOUBLE 7
140 #define TY_COMPLEX 8
141 #define TY_POINTER 9
142 #define TY_STRUCT 10
143 #define TY_USHORT 11
144 #define TY_UBYTE 12
145
146 #define LEN_IRAFHDR 25000
147 #define LEN_PIXHDR 1024
148 #define LEN_FITSHDR 11520
149
150 int check_immagic();
151 int irafgeti4();
152 float irafgetr4();
153 char *irafgetc2();
154 char *irafgetc();
155 char *iraf2str();
156 static char *same_path();
157 static void irafputr4();
158 static void irafputi4();
159 static void irafputc2();
160 static void irafputc();
161 static void str2iraf();
162 static int headswap=-1; /* =1 to swap data bytes of foreign IRAF file */
163 static void irafswap();
164 static void irafswap2();
165 static void irafswap4();
166 static void irafswap8();
167 int head_version ();
168 int pix_version ();
169 int irafncmp ();
170 static int machswap();
171 static int irafsize();
172
173 #define SECONDS_1970_TO_1980 315532800L
174
175 /* Subroutine: irafrhead
176 * Purpose: Open and read the iraf .imh file, translating it to FITS, too.
177 * Returns: NULL if failure, else pointer to IRAF .imh image header
178 * Notes: The imhdr format is defined in iraf/lib/imhdr.h, some of
179 * which defines or mimicked, above.
180 */
181
182 char *
irafrhead(filename,lihead)183 irafrhead (filename, lihead)
184
185 char *filename; /* Name of IRAF header file */
186 int *lihead; /* Length of IRAF image header in bytes (returned) */
187 {
188 FILE *fd;
189 int nbr;
190 char *irafheader;
191 int nbhead, nbytes;
192 int imhver;
193
194 headswap = -1;
195 *lihead = 0;
196
197 /* open the image header file */
198 fd = fopen (filename, "rb");
199 if (fd == NULL) {
200 fprintf (stderr, "IRAFRHEAD: cannot open file %s to read\n", filename);
201 return (NULL);
202 }
203
204 /* Find size of image header file */
205 if ((nbhead = irafsize (fd)) <= 0) {
206 fprintf (stderr, "IRAFRHEAD: cannot read file %s, size = %d\n",
207 filename, nbhead);
208 return (NULL);
209 }
210
211 /* allocate initial sized buffer */
212 nbytes = nbhead + 5000;
213 irafheader = (char *) calloc (nbytes/4, 4);
214 if (irafheader == NULL) {
215 (void)fprintf(stderr, "IRAFRHEAD Cannot allocate %d-byte header\n",
216 nbytes);
217 return (NULL);
218 }
219 *lihead = nbytes;
220
221 /* Read IRAF header */
222 nbr = fread (irafheader, 1, nbhead, fd);
223 fclose (fd);
224
225 /* Reject if header less than minimum length */
226 if (nbr < LEN_PIXHDR) {
227 (void)fprintf(stderr, "IRAFRHEAD header file %s: %d / %d bytes read.\n",
228 filename,nbr,LEN_PIXHDR);
229 free (irafheader);
230 return (NULL);
231 }
232
233 /* Check header magic word */
234 imhver = head_version (irafheader);
235 if (imhver < 1) {
236 free (irafheader);
237 (void)fprintf(stderr, "IRAFRHEAD: %s is not a valid IRAF image header\n",
238 filename);
239 return(NULL);
240 }
241
242 /* check number of image dimensions
243 if (imhver == 2)
244 ndim = irafgeti4 (irafheader, IM2_NDIM])
245 else
246 ndim = irafgeti4 (irafheader, IM_NDIM])
247 if (ndim < 2) {
248 free (irafheader);
249 (void)fprintf(stderr, "File %s does not contain 2d image\n", filename);
250 return (NULL);
251 } */
252
253 return (irafheader);
254 }
255
256
257 char *
irafrimage(fitsheader)258 irafrimage (fitsheader)
259
260 char *fitsheader; /* FITS image header (filled) */
261 {
262 FILE *fd;
263 char *bang;
264 int naxis, naxis1, naxis2, naxis3, npaxis1, npaxis2,bitpix, bytepix, pixswap, i;
265 char *image;
266 int nbr, nbimage, nbaxis, nbl, nbdiff, lpname;
267 char *pixheader;
268 char *linebuff, *pixchar;
269 int imhver, lpixhead, len;
270 char pixname[SZ_IM2PIXFILE+1];
271 char newpixname[SZ_IM2HDRFILE+1];
272
273 /* Convert pixel file name to character string */
274 hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname);
275
276 /* Drop trailing spaces */
277 lpname = strlen (pixname);
278 pixchar = pixname + lpname - 1;
279 while (*pixchar == ' ')
280 *pixchar = (char) 0;
281
282 hgeti4 (fitsheader, "PIXOFF", &lpixhead);
283
284 /* Open pixel file, ignoring machine name if present */
285 if ((bang = strchr (pixname, '!')) != NULL )
286 fd = fopen (bang + 1, "rb");
287 else
288 fd = fopen (pixname, "rb");
289
290 /* If not at pathname in header, try same directory as header file */
291 if (!fd) {
292 hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, newpixname);
293 len = strlen (newpixname);
294 newpixname[len-3] = 'p';
295 newpixname[len-2] = 'i';
296 newpixname[len-1] = 'x';
297 fd = fopen (newpixname, "rb");
298 }
299
300 /* Print error message and exit if pixel file is not found */
301 if (!fd) {
302 (void)fprintf(stderr,
303 "IRAFRIMAGE: Cannot open IRAF pixel file %s\n", pixname);
304 return (NULL);
305 }
306
307 /* Read pixel header */
308 pixheader = (char *) calloc (lpixhead/4, 4);
309 if (pixheader == NULL) {
310 (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte pixel header\n",
311 lpixhead);
312 return (NULL);
313 }
314 nbr = fread (pixheader, 1, lpixhead, fd);
315
316 /* Check size of pixel header */
317 if (nbr < lpixhead) {
318 (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n",
319 pixname,nbr,LEN_PIXHDR);
320 free (pixheader);
321 fclose (fd);
322 return (NULL);
323 }
324
325 /* check pixel header magic word */
326 imhver = pix_version (pixheader);
327 if (imhver < 1) {
328 (void)fprintf(stderr, "File %s not valid IRAF pixel file.\n", pixname);
329 free (pixheader);
330 fclose (fd);
331 return(NULL);
332 }
333 free (pixheader);
334
335 /* Find number of bytes to read */
336 hgeti4 (fitsheader,"NAXIS",&naxis);
337 hgeti4 (fitsheader,"NAXIS1",&naxis1);
338 hgeti4 (fitsheader,"NAXIS2",&naxis2);
339 hgeti4 (fitsheader,"NPAXIS1",&npaxis1);
340 hgeti4 (fitsheader,"NPAXIS2",&npaxis2);
341 hgeti4 (fitsheader,"BITPIX",&bitpix);
342 if (bitpix < 0)
343 bytepix = -bitpix / 8;
344 else
345 bytepix = bitpix / 8;
346
347 /* If either dimension is one and image is 3-D, read all three dimensions */
348 if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) {
349 hgeti4 (fitsheader,"NAXIS3",&naxis3);
350 nbimage = naxis1 * naxis2 * naxis3 * bytepix;
351 }
352 else {
353 nbimage = naxis1 * naxis2 * bytepix;
354 naxis3 = 1;
355 }
356
357 if (bytepix > 4)
358 image = (char *) calloc (nbimage/8, 8);
359 else if (bytepix > 2)
360 image = (char *) calloc (nbimage/4, 4);
361 else if (bytepix > 1)
362 image = (char *) calloc (nbimage/2, 2);
363 else
364 image = (char *) calloc (nbimage, 1);
365 if (image == NULL) {
366 (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte image buffer\n",
367 nbimage);
368 return (NULL);
369 }
370
371 /* Read IRAF image all at once if physical and image dimensions are the same */
372 if (npaxis1 == naxis1)
373 nbr = fread (image, 1, nbimage, fd);
374
375 /* Read IRAF image one line at a time if physical and image dimensions differ */
376 else {
377 nbdiff = (npaxis1 - naxis1) * bytepix;
378 nbaxis = naxis1 * bytepix;
379 linebuff = image;
380 nbr = 0;
381 if (naxis2 == 1 && naxis3 > 1)
382 naxis2 = naxis3;
383 for (i = 0; i < naxis2; i++) {
384 nbl = fread (linebuff, 1, nbaxis, fd);
385 nbr = nbr + nbl;
386 (void) fseek (fd, nbdiff, SEEK_CUR);
387 linebuff = linebuff + nbaxis;
388 }
389 }
390 fclose (fd);
391
392 /* Check size of image */
393 if (nbr < nbimage) {
394 (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n",
395 pixname,nbr,nbimage);
396 free (image);
397 return (NULL);
398 }
399
400 /* Byte-reverse image, if necessary */
401 pixswap = 0;
402 hgetl (fitsheader, "PIXSWAP", &pixswap);
403 if (pixswap)
404 irafswap (bitpix, image, nbimage);
405
406 return (image);
407 }
408
409
410 /* Return IRAF image format version number from magic word in IRAF header*/
411
412 int
head_version(irafheader)413 head_version (irafheader)
414
415 char *irafheader; /* IRAF image header from file */
416
417 {
418
419 /* Check header file magic word */
420 if (irafncmp (irafheader, "imhdr", 5) != 0 ) {
421 if (strncmp (irafheader, "imhv2", 5) != 0)
422 return (0);
423 else
424 return (2);
425 }
426 else
427 return (1);
428 }
429
430
431 /* Return IRAF image format version number from magic word in IRAF pixel file */
432
433 int
pix_version(irafheader)434 pix_version (irafheader)
435
436 char *irafheader; /* IRAF image header from file */
437
438 {
439
440 /* Check pixel file header magic word */
441 if (irafncmp (irafheader, "impix", 5) != 0) {
442 if (strncmp (irafheader, "impv2", 5) != 0)
443 return (0);
444 else
445 return (2);
446 }
447 else
448 return (1);
449 }
450
451
452 /* Verify that file is valid IRAF imhdr or impix by checking first 5 chars
453 * Returns: 0 on success, 1 on failure */
454
455 int
irafncmp(irafheader,teststring,nc)456 irafncmp (irafheader, teststring, nc)
457
458 char *irafheader; /* IRAF image header from file */
459 char *teststring; /* C character string to compare */
460 int nc; /* Number of characters to compate */
461
462 {
463 char *line;
464
465 headswap = -1;
466 if ((line = iraf2str (irafheader, nc)) == NULL)
467 return (1);
468 if (strncmp (line, teststring, nc) == 0) {
469 free (line);
470 return (0);
471 }
472 else {
473 free (line);
474 return (1);
475 }
476 }
477
478 /* Convert IRAF image header to FITS image header, returning FITS header */
479
480 char *
iraf2fits(hdrname,irafheader,nbiraf,nbfits)481 iraf2fits (hdrname, irafheader, nbiraf, nbfits)
482
483 char *hdrname; /* IRAF header file name (may be path) */
484 char *irafheader; /* IRAF image header */
485 int nbiraf; /* Number of bytes in IRAF header */
486 int *nbfits; /* Number of bytes in FITS header (returned) */
487
488 {
489 char *objname; /* object name from FITS file */
490 int lstr, i, j, k, ib, nax, nbits, nl;
491 int lname = 0;
492 char *pixname, *newpixname, *bang, *chead;
493 char *fitsheader;
494 int nblock, nlines;
495 char *fhead, *fhead1, *fp, endline[81];
496 char irafchar;
497 char fitsline[81];
498 char *dstring;
499 int pixtype;
500 int imhver, n, imu, pixoff, impixoff, immax, immin, imtime;
501 int imndim, imlen, imphyslen, impixtype, pixswap, hpixswap, mtime;
502 float rmax, rmin;
503
504 headswap = -1;
505
506 /* Set up last line of FITS header */
507 (void)strncpy (endline,"END", 3);
508 for (i = 3; i < 80; i++)
509 endline[i] = ' ';
510 endline[80] = 0;
511
512 /* Check header magic word */
513 imhver = head_version (irafheader);
514 if (imhver < 1) {
515 (void)fprintf(stderr, "File %s not valid IRAF image header\n",
516 hdrname);
517 return(NULL);
518 }
519 if (imhver == 2) {
520 nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81);
521 imndim = IM2_NDIM;
522 imlen = IM2_LEN;
523 imphyslen = IM2_PHYSLEN;
524 impixtype = IM2_PIXTYPE;
525 impixoff = IM2_PIXOFF;
526 imtime = IM2_MTIME;
527 immax = IM2_MAX;
528 immin = IM2_MIN;
529 }
530 else {
531 nlines = 24 + ((nbiraf - LEN_IMHDR) / 162);
532 imndim = IM_NDIM;
533 imlen = IM_LEN;
534 imphyslen = IM_PHYSLEN;
535 impixtype = IM_PIXTYPE;
536 impixoff = IM_PIXOFF;
537 imtime = IM_MTIME;
538 immax = IM_MAX;
539 immin = IM_MIN;
540 }
541
542 /* Initialize FITS header */
543 nblock = (nlines * 80) / 2880;
544 *nbfits = (nblock + 5) * 2880 + 4;
545 fitsheader = (char *) calloc (*nbfits, 1);
546 if (fitsheader == NULL) {
547 (void)fprintf(stderr, "IRAF2FITS Cannot allocate %d-byte FITS header\n",
548 *nbfits);
549 return (NULL);
550 }
551 hlength (fitsheader, *nbfits);
552 fhead = fitsheader;
553 (void)strncpy (fitsheader, endline, 80);
554 hputl (fitsheader, "SIMPLE", 1);
555 fhead = fhead + 80;
556
557 /* Set pixel size in FITS header */
558 pixtype = irafgeti4 (irafheader, impixtype);
559 switch (pixtype) {
560 case TY_CHAR:
561 nbits = 8;
562 break;
563 case TY_UBYTE:
564 nbits = 8;
565 break;
566 case TY_SHORT:
567 nbits = 16;
568 break;
569 case TY_USHORT:
570 nbits = -16;
571 break;
572 case TY_INT:
573 case TY_LONG:
574 nbits = 32;
575 break;
576 case TY_REAL:
577 nbits = -32;
578 break;
579 case TY_DOUBLE:
580 nbits = -64;
581 break;
582 default:
583 (void)fprintf(stderr,"Unsupported data type: %d\n", pixtype);
584 return (NULL);
585 }
586 hputi4 (fitsheader,"BITPIX",nbits);
587 hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type");
588 fhead = fhead + 80;
589
590 /* Set image dimensions in FITS header */
591 nax = irafgeti4 (irafheader, imndim);
592 hputi4 (fitsheader,"NAXIS",nax);
593 hputcom (fitsheader,"NAXIS", "IRAF .imh naxis");
594 fhead = fhead + 80;
595
596 n = irafgeti4 (irafheader, imlen);
597 hputi4 (fitsheader, "NAXIS1", n);
598 hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]");
599 fhead = fhead + 80;
600
601 if (nax > 1) {
602 n = irafgeti4 (irafheader, imlen+4);
603 hputi4 (fitsheader, "NAXIS2", n);
604 hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]");
605 }
606 else
607 hputi4 (fitsheader, "NAXIS2", 1);
608 hputcom (fitsheader,"NAXIS2", "IRAF .imh naxis[2]");
609 fhead = fhead + 80;
610
611 if (nax > 2) {
612 n = irafgeti4 (irafheader, imlen+8);
613 hputi4 (fitsheader, "NAXIS3", n);
614 hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]");
615 fhead = fhead + 80;
616 }
617 if (nax > 3) {
618 n = irafgeti4 (irafheader, imlen+12);
619 hputi4 (fitsheader, "NAXIS4", n);
620 hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]");
621 fhead = fhead + 80;
622 }
623
624 /* Set object name in FITS header */
625 if (imhver == 2)
626 objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE);
627 else
628 objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE);
629 if ((lstr = strlen (objname)) < 8) {
630 for (i = lstr; i < 8; i++)
631 objname[i] = ' ';
632 objname[8] = 0;
633 }
634 hputs (fitsheader,"OBJECT",objname);
635 hputcom (fitsheader,"OBJECT", "IRAF .imh title");
636 free (objname);
637 fhead = fhead + 80;
638
639 /* Save physical axis lengths so image file can be read */
640 n = irafgeti4 (irafheader, imphyslen);
641 hputi4 (fitsheader, "NPAXIS1", n);
642 hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]");
643 fhead = fhead + 80;
644 if (nax > 1) {
645 n = irafgeti4 (irafheader, imphyslen+4);
646 hputi4 (fitsheader, "NPAXIS2", n);
647 hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]");
648 fhead = fhead + 80;
649 }
650 if (nax > 2) {
651 n = irafgeti4 (irafheader, imphyslen+8);
652 hputi4 (fitsheader, "NPAXIS3", n);
653 hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]");
654 fhead = fhead + 80;
655 }
656 if (nax > 3) {
657 n = irafgeti4 (irafheader, imphyslen+12);
658 hputi4 (fitsheader, "NPAXIS4", n);
659 hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]");
660 fhead = fhead + 80;
661 }
662
663 /* Save image minimum and maximum in header */
664 rmax = irafgetr4 (irafheader, immax);
665 rmin = irafgetr4 (irafheader, immin);
666 if (rmin != rmax) {
667 hputr4 (fitsheader, "IRAFMIN", &rmin);
668 fhead = fhead + 80;
669 hputcom (fitsheader,"IRAFMIN", "IRAF .imh minimum");
670 hputr4 (fitsheader, "IRAFMAX", &rmax);
671 hputcom (fitsheader,"IRAFMAX", "IRAF .imh maximum");
672 fhead = fhead + 80;
673 }
674
675 /* Save image header filename in header */
676 nl = hputm (fitsheader,"IMHFIL",hdrname);
677 if (nl > 0) {
678 lname = strlen (hdrname);
679 strcpy (fitsline, "IRAF header file name");
680 if (lname < 43)
681 hputcom (fitsheader,"IMHFIL_1", fitsline);
682 else if (lname > 67 && lname < 110)
683 hputcom (fitsheader,"IMHFIL_2", fitsline);
684 else if (lname > 134 && lname < 177)
685 hputcom (fitsheader,"IMHFIL_3", fitsline);
686 }
687 if (nl > 0) fhead = fhead + (nl * 80);
688
689 /* Save image pixel file pathname in header */
690 if (imhver == 2)
691 pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE);
692 else
693 pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE);
694 if (strncmp(pixname, "HDR", 3) == 0 ) {
695 newpixname = same_path (pixname, hdrname);
696 free (pixname);
697 pixname = newpixname;
698 }
699 if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
700 newpixname = same_path (pixname, hdrname);
701 free (pixname);
702 pixname = newpixname;
703 }
704
705 if ((bang = strchr (pixname, '!')) != NULL )
706 nl = hputm (fitsheader,"PIXFIL",bang+1);
707 else
708 nl = hputm (fitsheader,"PIXFIL",pixname);
709 free (pixname);
710 if (nl > 0) {
711 strcpy (fitsline, "IRAF .pix pixel file");
712 if (lname < 43)
713 hputcom (fitsheader,"PIXFIL_1", fitsline);
714 else if (lname > 67 && lname < 110)
715 hputcom (fitsheader,"PIXFIL_2", fitsline);
716 else if (lname > 134 && lname < 177)
717 hputcom (fitsheader,"PIXFIL_3", fitsline);
718 }
719 if (nl > 0) fhead = fhead + (nl * 80);
720
721 /* Save image offset from star of pixel file */
722 pixoff = irafgeti4 (irafheader, impixoff);
723 pixoff = (pixoff - 1) * 2;
724 hputi4 (fitsheader, "PIXOFF", pixoff);
725 hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)");
726 fhead = fhead + 80;
727
728 /* Save IRAF file format version in header */
729 hputi4 (fitsheader,"IMHVER",imhver);
730 hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)");
731 fhead = fhead + 80;
732
733 /* Set flag if header numbers are byte-reversed on this machine */
734 if (machswap() != headswap)
735 hputl (fitsheader, "HEADSWAP", 1);
736 else
737 hputl (fitsheader, "HEADSWAP", 0);
738 hputcom (fitsheader,"HEADSWAP", "IRAF header, FITS byte orders differ if T");
739 fhead = fhead + 80;
740
741 /* Set flag if image pixels are byte-reversed on this machine */
742 if (imhver == 2) {
743 hpixswap = irafgeti4 (irafheader, IM2_SWAPPED);
744 if (headswap && !hpixswap)
745 pixswap = 1;
746 else if (!headswap && hpixswap)
747 pixswap = 1;
748 else
749 pixswap = 0;
750 }
751 else
752 pixswap = headswap;
753 if (machswap() != pixswap)
754 hputl (fitsheader, "PIXSWAP", 1);
755 else
756 hputl (fitsheader, "PIXSWAP", 0);
757 hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T");
758 fhead = fhead + 80;
759
760 /* Read modification time */
761 mtime = irafgeti4 (irafheader, imtime);
762 if (mtime == 0)
763 dstring = lt2fd ();
764 else
765 dstring = tsi2fd (mtime);
766 hputs (fitsheader, "DATE-MOD", dstring);
767 hputcom (fitsheader,"DATE-MOD", "Date of latest file modification");
768 free (dstring);
769 fhead = fhead + 80;
770
771 /* Add user portion of IRAF header to FITS header */
772 fitsline[80] = 0;
773 if (imhver == 2) {
774 imu = LEN_IM2HDR;
775 chead = irafheader;
776 j = 0;
777 for (k = 0; k < 80; k++)
778 fitsline[k] = ' ';
779 for (i = imu; i < nbiraf; i++) {
780 irafchar = chead[i];
781 if (irafchar == 0)
782 break;
783 else if (irafchar == 10) {
784 (void)strncpy (fhead, fitsline, 80);
785 /* fprintf (stderr,"%80s\n",fitsline); */
786 if (strncmp (fitsline, "OBJECT ", 7) != 0) {
787 fhead = fhead + 80;
788 }
789 for (k = 0; k < 80; k++)
790 fitsline[k] = ' ';
791 j = 0;
792 }
793 else {
794 if (j > 80) {
795 if (strncmp (fitsline, "OBJECT ", 7) != 0) {
796 (void)strncpy (fhead, fitsline, 80);
797 /* fprintf (stderr,"%80s\n",fitsline); */
798 j = 9;
799 fhead = fhead + 80;
800 }
801 for (k = 0; k < 80; k++)
802 fitsline[k] = ' ';
803 }
804 if (irafchar > 32 && irafchar < 127)
805 fitsline[j] = irafchar;
806 j++;
807 }
808 }
809 }
810 else {
811 imu = LEN_IMHDR;
812 chead = irafheader;
813 if (headswap == 1)
814 ib = 0;
815 else
816 ib = 1;
817 for (k = 0; k < 80; k++)
818 fitsline[k] = ' ';
819 j = 0;
820 for (i = imu; i < nbiraf; i=i+2) {
821 irafchar = chead[i+ib];
822 if (irafchar == 0)
823 break;
824 else if (irafchar == 10) {
825 if (strncmp (fitsline, "OBJECT ", 7) != 0) {
826 (void)strncpy (fhead, fitsline, 80);
827 fhead = fhead + 80;
828 }
829 /* fprintf (stderr,"%80s\n",fitsline); */
830 j = 0;
831 for (k = 0; k < 80; k++)
832 fitsline[k] = ' ';
833 }
834 else {
835 if (j > 80) {
836 if (strncmp (fitsline, "OBJECT ", 7) != 0) {
837 (void)strncpy (fhead, fitsline, 80);
838 j = 9;
839 fhead = fhead + 80;
840 }
841 /* fprintf (stderr,"%80s\n",fitsline); */
842 for (k = 0; k < 80; k++)
843 fitsline[k] = ' ';
844 }
845 if (irafchar > 32 && irafchar < 127)
846 fitsline[j] = irafchar;
847 j++;
848 }
849 }
850 }
851
852 /* Add END to last line */
853 (void)strncpy (fhead, endline, 80);
854
855 /* Find end of last 2880-byte block of header */
856 fhead = ksearch (fitsheader, "END") + 80;
857 nblock = *nbfits / 2880;
858 fhead1 = fitsheader + (nblock * 2880);
859
860 /* Pad rest of header with spaces */
861 strncpy (endline," ",3);
862 for (fp = fhead; fp < fhead1; fp = fp + 80) {
863 (void)strncpy (fp, endline,80);
864 }
865
866 return (fitsheader);
867 }
868
869
870 int
irafwhead(hdrname,lhead,irafheader,fitsheader)871 irafwhead (hdrname, lhead, irafheader, fitsheader)
872
873 char *hdrname; /* Name of IRAF header file */
874 int lhead; /* Length of IRAF header */
875 char *irafheader; /* IRAF header */
876 char *fitsheader; /* FITS image header */
877
878 {
879 int fd;
880 int nbw, nbhead, lphead, pixswap;
881
882 /* Get rid of redundant header information */
883 hgeti4 (fitsheader, "PIXOFF", &lphead);
884 hgeti4 (fitsheader, "PIXSWAP", &pixswap);
885
886 /* Write IRAF header file */
887
888 /* Convert FITS header to IRAF header */
889 irafheader = fits2iraf (fitsheader, irafheader, lhead, &nbhead);
890 if (irafheader == NULL) {
891 fprintf (stderr, "IRAFWIMAGE: file %s header error\n", hdrname);
892 return (-1);
893 }
894
895 /* Open the output file */
896 if (!access (hdrname, 0)) {
897 fd = open (hdrname, O_WRONLY);
898 if (fd < 3) {
899 fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", hdrname);
900 return (0);
901 }
902 }
903 else {
904 fd = open (hdrname, O_RDWR+O_CREAT, 0666);
905 if (fd < 3) {
906 fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", hdrname);
907 return (0);
908 }
909 }
910
911 /* Write IRAF header to disk file */
912 nbw = write (fd, irafheader, nbhead);
913 (void) ftruncate (fd, nbhead);
914 close (fd);
915 if (nbw < nbhead) {
916 (void)fprintf(stderr, "IRAF header file %s: %d / %d bytes written.\n",
917 hdrname, nbw, nbhead);
918 return (-1);
919 }
920
921 return (nbw);
922 }
923
924 /* IRAFWIMAGE -- write IRAF .imh header file and .pix image file
925 * No matter what the input, this always writes in the local byte order */
926
927 int
irafwimage(hdrname,lhead,irafheader,fitsheader,image)928 irafwimage (hdrname, lhead, irafheader, fitsheader, image )
929
930 char *hdrname; /* Name of IRAF header file */
931 int lhead; /* Length of IRAF header */
932 char *irafheader; /* IRAF header */
933 char *fitsheader; /* FITS image header */
934 char *image; /* IRAF image */
935
936 {
937 int fd;
938 char *bang;
939 int nbw, bytepix, bitpix, naxis, naxis1, naxis2, nbimage, lphead;
940 char *pixn, *newpixname;
941 char pixname[SZ_IM2PIXFILE+1];
942 int imhver, pixswap;
943
944 hgeti4 (fitsheader, "IMHVER", &imhver);
945
946 if (!hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname)) {
947 if (imhver == 2)
948 pixn = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE);
949 else
950 pixn = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE);
951 if (strncmp(pixn, "HDR", 3) == 0 ) {
952 newpixname = same_path (pixn, hdrname);
953 strcpy (pixname, newpixname);
954 free (newpixname);
955 }
956 else {
957 if ((bang = strchr (pixn, '!')) != NULL )
958 strcpy (pixname, bang+1);
959 else
960 strcpy (pixname, pixn);
961 }
962 free (pixn);
963 }
964
965 /* Find number of bytes to write */
966 hgeti4 (fitsheader,"NAXIS",&naxis);
967 hgeti4 (fitsheader,"NAXIS1",&naxis1);
968 hgeti4 (fitsheader,"NAXIS2",&naxis2);
969 hgeti4 (fitsheader,"BITPIX",&bitpix);
970 if (bitpix < 0)
971 bytepix = -bitpix / 8;
972 else
973 bytepix = bitpix / 8;
974
975 /* If either dimension is one and image is 3-D, read all three dimensions */
976 if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) {
977 int naxis3;
978 hgeti4 (fitsheader,"NAXIS3",&naxis3);
979 nbimage = naxis1 * naxis2 * naxis3 * bytepix;
980 }
981 else
982 nbimage = naxis1 * naxis2 * bytepix;
983
984 /* Read information about pixel file from header */
985 hgeti4 (fitsheader, "PIXOFF", &lphead);
986 hgeti4 (fitsheader, "PIXSWAP", &pixswap);
987
988 /* Write IRAF header file */
989 if (irafwhead (hdrname, lhead, irafheader, fitsheader))
990 return (0);
991
992 /* Open the output file */
993 if (!access (pixname, 0)) {
994 fd = open (pixname, O_WRONLY);
995 if (fd < 3) {
996 fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", pixname);
997 return (0);
998 }
999 }
1000 else {
1001 fd = open (pixname, O_RDWR+O_CREAT, 0666);
1002 if (fd < 3) {
1003 fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", pixname);
1004 return (0);
1005 }
1006 }
1007
1008 /* Write header to IRAF pixel file */
1009 if (imhver == 2)
1010 irafputc ("impv2", irafheader, 0, 5);
1011 else
1012 irafputc2 ("impix", irafheader, 0, 5);
1013 nbw = write (fd, irafheader, lphead);
1014
1015 /* Byte-reverse image, if necessary */
1016 if (pixswap)
1017 irafswap (bitpix, image, nbimage);
1018
1019 /* Write data to IRAF pixel file */
1020 nbw = write (fd, image, nbimage);
1021 close (fd);
1022
1023 return (nbw);
1024 }
1025
1026
1027 /* Put filename and header path together */
1028
1029 static char *
same_path(pixname,hdrname)1030 same_path (pixname, hdrname)
1031
1032 char *pixname; /* IRAF pixel file pathname */
1033 char *hdrname; /* IRAF image header file pathname */
1034
1035 {
1036 int len, plen;
1037 char *newpixname;
1038
1039 newpixname = (char *) calloc (SZ_IM2PIXFILE, 1);
1040
1041 /* Pixel file is in same directory as header */
1042 if (strncmp(pixname, "HDR$", 4) == 0 ) {
1043 (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);
1044
1045 /* find the end of the pathname */
1046 len = strlen (newpixname);
1047 #ifndef VMS
1048 while( (len > 0) && (newpixname[len-1] != '/') )
1049 #else
1050 while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') )
1051 #endif
1052 len--;
1053
1054 /* add name */
1055 newpixname[len] = '\0';
1056 plen = strlen (pixname) - 4;
1057 if (len + plen > SZ_IM2PIXFILE)
1058 (void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE - len);
1059 else
1060 (void)strncat (newpixname, &pixname[4], plen);
1061 }
1062
1063 /* Bare pixel file with no path is assumed to be same as HDR$filename */
1064 else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
1065 (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);
1066
1067 /* find the end of the pathname */
1068 len = strlen (newpixname);
1069 #ifndef VMS
1070 while( (len > 0) && (newpixname[len-1] != '/') )
1071 #else
1072 while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') )
1073 #endif
1074 len--;
1075
1076 /* add name */
1077 newpixname[len] = '\0';
1078 (void)strncat (newpixname, pixname, SZ_IM2PIXFILE);
1079 }
1080
1081 /* Pixel file has same name as header file, but with .pix extension */
1082 else if (strncmp (pixname, "HDR", 3) == 0) {
1083
1084 /* load entire header name string into name buffer */
1085 (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);
1086 len = strlen (newpixname);
1087 newpixname[len-3] = 'p';
1088 newpixname[len-2] = 'i';
1089 newpixname[len-1] = 'x';
1090 }
1091
1092 return (newpixname);
1093 }
1094
1095 /* Convert FITS image header to IRAF image header, returning IRAF header */
1096 /* No matter what the input, this always writes in the local byte order */
1097
1098 char *
fits2iraf(fitsheader,irafheader,nbhead,nbiraf)1099 fits2iraf (fitsheader, irafheader, nbhead, nbiraf)
1100
1101 char *fitsheader; /* FITS image header */
1102 char *irafheader; /* IRAF image header (returned updated) */
1103 int nbhead; /* Length of IRAF header */
1104 int *nbiraf; /* Length of returned IRAF header */
1105
1106 {
1107 int i, n, pixoff, lhdrdir;
1108 short *irafp, *irafs, *irafu;
1109 char *iraf2u, *iraf2p, *filename, *hdrdir;
1110 char *fitsend, *fitsp, pixfile[SZ_IM2PIXFILE], hdrfile[SZ_IM2HDRFILE];
1111 char title[SZ_IM2TITLE], temp[80];
1112 int nax, nlfits, imhver, nbits, pixtype, hdrlength, mtime;
1113 int imndim, imlen, imphyslen, impixtype, imhlen, imtime, immax, immin;
1114 float rmax, rmin;
1115
1116 hgeti4 (fitsheader, "IMHVER", &imhver);
1117 hdel (fitsheader, "IMHVER");
1118 hdel (fitsheader, "IMHVER");
1119 hgetl (fitsheader, "HEADSWAP", &headswap);
1120 hdel (fitsheader, "HEADSWAP");
1121 hdel (fitsheader, "HEADSWAP");
1122 if (imhver == 2) {
1123 imhlen = IM2_HDRLEN;
1124 imndim = IM2_NDIM;
1125 imlen = IM2_LEN;
1126 imtime = IM2_MTIME;
1127 imphyslen = IM2_PHYSLEN;
1128 impixtype = IM2_PIXTYPE;
1129 immax = IM2_MAX;
1130 immin = IM2_MIN;
1131 }
1132 else {
1133 imhlen = IM_HDRLEN;
1134 imndim = IM_NDIM;
1135 imlen = IM_LEN;
1136 imtime = IM_MTIME;
1137 imphyslen = IM_PHYSLEN;
1138 impixtype = IM_PIXTYPE;
1139 immax = IM_MAX;
1140 immin = IM_MIN;
1141 }
1142
1143 /* Delete FITS header keyword not needed by IRAF */
1144 hdel (fitsheader,"SIMPLE");
1145
1146 /* Set IRAF image data type */
1147 hgeti4 (fitsheader,"BITPIX", &nbits);
1148 switch (nbits) {
1149 case 8:
1150 pixtype = TY_CHAR;
1151 break;
1152 case -8:
1153 pixtype = TY_UBYTE;
1154 break;
1155 case 16:
1156 pixtype = TY_SHORT;
1157 break;
1158 case -16:
1159 pixtype = TY_USHORT;
1160 break;
1161 case 32:
1162 pixtype = TY_INT;
1163 break;
1164 case -32:
1165 pixtype = TY_REAL;
1166 break;
1167 case -64:
1168 pixtype = TY_DOUBLE;
1169 break;
1170 default:
1171 (void)fprintf(stderr,"Unsupported data type: %d\n", nbits);
1172 return (NULL);
1173 }
1174 irafputi4 (irafheader, impixtype, pixtype);
1175 hdel (fitsheader,"BITPIX");
1176
1177 /* Set IRAF image dimensions */
1178 hgeti4 (fitsheader,"NAXIS",&nax);
1179 irafputi4 (irafheader, imndim, nax);
1180 hdel (fitsheader,"NAXIS");
1181
1182 hgeti4 (fitsheader, "NAXIS1", &n);
1183 irafputi4 (irafheader, imlen, n);
1184 irafputi4 (irafheader, imphyslen, n);
1185 hdel (fitsheader,"NAXIS1");
1186
1187 hgeti4 (fitsheader,"NAXIS2",&n);
1188 irafputi4 (irafheader, imlen+4, n);
1189 irafputi4 (irafheader, imphyslen+4, n);
1190 hdel (fitsheader,"NAXIS2");
1191
1192 if (nax > 2) {
1193 hgeti4 (fitsheader,"NAXIS3",&n);
1194 irafputi4 (irafheader, imlen+8, n);
1195 irafputi4 (irafheader, imphyslen+8, n);
1196 hdel (fitsheader,"NAXIS3");
1197 }
1198
1199 if (nax > 3) {
1200 hgeti4 (fitsheader,"NAXIS4",&n);
1201 irafputi4 (irafheader, imlen+12, n);
1202 irafputi4 (irafheader, imphyslen+12, n);
1203 hdel (fitsheader,"NAXIS4");
1204 }
1205
1206 /* Set image pixel value limits */
1207 rmin = 0.0;
1208 hgetr4 (fitsheader, "IRAFMIN", &rmin);
1209 rmax = 0.0;
1210 hgetr4 (fitsheader, "IRAFMAX", &rmax);
1211 if (rmin != rmax) {
1212 irafputr4 (irafheader, immax, rmax);
1213 irafputr4 (irafheader, immin, rmin);
1214 }
1215 hdel (fitsheader, "IRAFMIN");
1216 hdel (fitsheader, "IRAFMAX");
1217
1218 /* Replace pixel file name, if it is in the FITS header */
1219 if (hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixfile)) {
1220 if (strchr (pixfile, '/')) {
1221 if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, hdrfile)) {
1222 hdrdir = strrchr (hdrfile, '/');
1223 if (hdrdir != NULL) {
1224 lhdrdir = hdrdir - hdrfile + 1;
1225 if (!strncmp (pixfile, hdrfile, lhdrdir)) {
1226 filename = pixfile + lhdrdir;
1227 strcpy (temp, "HDR$");
1228 strcat (temp,filename);
1229 strcpy (pixfile, temp);
1230 }
1231 }
1232 if (pixfile[0] != '/' && pixfile[0] != 'H') {
1233 strcpy (temp, "HDR$");
1234 strcat (temp,pixfile);
1235 strcpy (pixfile, temp);
1236 }
1237 }
1238 }
1239
1240 if (imhver == 2)
1241 irafputc (pixfile, irafheader, IM2_PIXFILE, SZ_IM2PIXFILE);
1242 else
1243 irafputc2 (pixfile, irafheader, IM_PIXFILE, SZ_IMPIXFILE);
1244 hdel (fitsheader,"PIXFIL_1");
1245 hdel (fitsheader,"PIXFIL_2");
1246 hdel (fitsheader,"PIXFIL_3");
1247 hdel (fitsheader,"PIXFIL_4");
1248 }
1249
1250 /* Replace header file name, if it is in the FITS header */
1251 if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, pixfile)) {
1252 if (!strchr (pixfile,'/') && !strchr (pixfile,'$')) {
1253 strcpy (temp, "HDR$");
1254 strcat (temp,pixfile);
1255 strcpy (pixfile, temp);
1256 }
1257 if (imhver == 2)
1258 irafputc (pixfile, irafheader, IM2_HDRFILE, SZ_IM2HDRFILE);
1259 else
1260 irafputc2 (pixfile, irafheader, IM_HDRFILE, SZ_IMHDRFILE);
1261 hdel (fitsheader, "IMHFIL_1");
1262 hdel (fitsheader, "IMHFIL_2");
1263 hdel (fitsheader, "IMHFIL_3");
1264 hdel (fitsheader, "IMHFIL_4");
1265 }
1266
1267 /* Replace image title, if it is in the FITS header */
1268 if (hgets (fitsheader, "OBJECT", SZ_IM2TITLE, title)) {
1269 if (imhver == 2)
1270 irafputc (title, irafheader, IM2_TITLE, SZ_IM2TITLE);
1271 else
1272 irafputc2 (title, irafheader, IM_TITLE, SZ_IMTITLE);
1273 hdel (fitsheader, "OBJECT");
1274 }
1275 hgeti4 (fitsheader, "PIXOFF", &pixoff);
1276 hdel (fitsheader, "PIXOFF");
1277 hdel (fitsheader, "PIXOFF");
1278 hdel (fitsheader, "PIXSWAP");
1279 hdel (fitsheader, "PIXSWAP");
1280 hdel (fitsheader, "DATE-MOD");
1281 hdel (fitsheader, "DATE-MOD");
1282 fitsend = ksearch (fitsheader,"END");
1283
1284 /* Find length of FITS header */
1285 fitsend = ksearch (fitsheader,"END");
1286 nlfits = ((fitsend - fitsheader) / 80);
1287
1288 /* Find new length of IRAF header */
1289 if (imhver == 2)
1290 *nbiraf = LEN_IM2HDR + (81 * nlfits);
1291 else
1292 *nbiraf = LEN_IMHDR + (162 * nlfits);
1293 if (*nbiraf > nbhead)
1294 irafheader = realloc (irafheader, *nbiraf);
1295
1296 /* Reset modification time */
1297 mtime = lt2tsi ();
1298 irafputi4 (irafheader, imtime, mtime);
1299
1300 /* Replace user portion of IRAF header with remaining FITS header */
1301 if (imhver == 2) {
1302 iraf2u = irafheader + LEN_IM2HDR;
1303 iraf2p = iraf2u;
1304 for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) {
1305 for (i = 0; i < 80; i++)
1306 *iraf2p++ = fitsp[i];
1307 *iraf2p++ = 10;
1308 }
1309 *iraf2p++ = 0;
1310 *nbiraf = iraf2p - irafheader;
1311 hdrlength = 1 + *nbiraf / 2;
1312 }
1313 else {
1314 irafs = (short *)irafheader;
1315 irafu = irafs + (LEN_IMHDR / 2);
1316 irafp = irafu;
1317 for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) {
1318 for (i = 0; i < 80; i++)
1319 *irafp++ = (short) fitsp[i];
1320 *irafp++ = 10;
1321 }
1322 *irafp++ = 0;
1323 *irafp++ = 32;
1324 *nbiraf = 2 * (irafp - irafs);
1325 hdrlength = *nbiraf / 4;
1326 }
1327
1328 /* Length of header file */
1329 irafputi4 (irafheader, imhlen, hdrlength);
1330
1331 /* Offset in .pix file to first pixel data
1332 hputi4 (fitsheader, "PIXOFF", pixoff); */
1333
1334 /* Return number of bytes in new IRAF header */
1335 return (irafheader);
1336 }
1337
1338
1339 int
irafgeti4(irafheader,offset)1340 irafgeti4 (irafheader, offset)
1341
1342 char *irafheader; /* IRAF image header */
1343 int offset; /* Number of bytes to skip before number */
1344
1345 {
1346 char *ctemp, *cheader;
1347 int temp;
1348
1349 cheader = irafheader;
1350 ctemp = (char *) &temp;
1351
1352 /* If header swap flag not set, set it now */
1353 if (headswap < 0) {
1354 if (cheader[offset] > 0)
1355 headswap = 1;
1356 else
1357 headswap = 0;
1358 }
1359
1360 if (machswap() != headswap) {
1361 ctemp[3] = cheader[offset];
1362 ctemp[2] = cheader[offset+1];
1363 ctemp[1] = cheader[offset+2];
1364 ctemp[0] = cheader[offset+3];
1365 }
1366 else {
1367 ctemp[0] = cheader[offset];
1368 ctemp[1] = cheader[offset+1];
1369 ctemp[2] = cheader[offset+2];
1370 ctemp[3] = cheader[offset+3];
1371 }
1372 return (temp);
1373 }
1374
1375
1376 float
irafgetr4(irafheader,offset)1377 irafgetr4 (irafheader, offset)
1378
1379 char *irafheader; /* IRAF image header */
1380 int offset; /* Number of bytes to skip before number */
1381
1382 {
1383 char *ctemp, *cheader;
1384 float temp;
1385
1386 cheader = irafheader;
1387 ctemp = (char *) &temp;
1388
1389 /* If header swap flag not set, set it now */
1390 if (headswap < 0) {
1391 if (cheader[offset] > 0)
1392 headswap = 1;
1393 else
1394 headswap = 0;
1395 }
1396
1397 if (machswap() != headswap) {
1398 ctemp[3] = cheader[offset];
1399 ctemp[2] = cheader[offset+1];
1400 ctemp[1] = cheader[offset+2];
1401 ctemp[0] = cheader[offset+3];
1402 }
1403 else {
1404 ctemp[0] = cheader[offset];
1405 ctemp[1] = cheader[offset+1];
1406 ctemp[2] = cheader[offset+2];
1407 ctemp[3] = cheader[offset+3];
1408 }
1409 return (temp);
1410 }
1411
1412
1413 /* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */
1414
1415 char *
irafgetc2(irafheader,offset,nc)1416 irafgetc2 (irafheader, offset, nc)
1417
1418 char *irafheader; /* IRAF image header */
1419 int offset; /* Number of bytes to skip before string */
1420 int nc; /* Maximum number of characters in string */
1421
1422 {
1423 char *irafstring, *string;
1424
1425 irafstring = irafgetc (irafheader, offset, 2*(nc+1));
1426 string = iraf2str (irafstring, nc);
1427 free (irafstring);
1428
1429 return (string);
1430 }
1431
1432
1433 /* IRAFGETC -- Get character string from arbitrary part of IRAF header */
1434
1435 char *
irafgetc(irafheader,offset,nc)1436 irafgetc (irafheader, offset, nc)
1437
1438 char *irafheader; /* IRAF image header */
1439 int offset; /* Number of bytes to skip before string */
1440 int nc; /* Maximum number of characters in string */
1441
1442 {
1443 char *ctemp, *cheader;
1444 int i;
1445
1446 cheader = irafheader;
1447 ctemp = (char *) calloc (nc+1, 1);
1448 if (ctemp == NULL) {
1449 (void)fprintf(stderr, "IRAFGETC Cannot allocate %d-byte variable\n",
1450 nc+1);
1451 return (NULL);
1452 }
1453 for (i = 0; i < nc; i++) {
1454 ctemp[i] = cheader[offset+i];
1455 if (ctemp[i] > 0 && ctemp[i] < 32)
1456 ctemp[i] = ' ';
1457 }
1458
1459 return (ctemp);
1460 }
1461
1462
1463 /* Convert IRAF 2-byte/char string to 1-byte/char string */
1464
1465 char *
iraf2str(irafstring,nchar)1466 iraf2str (irafstring, nchar)
1467
1468 char *irafstring; /* IRAF 2-byte/character string */
1469 int nchar; /* Number of characters in string */
1470 {
1471 char *string;
1472 int i, j;
1473
1474 /* Set swap flag according to position of nulls in 2-byte characters */
1475 if (headswap < 0) {
1476 if (irafstring[0] != 0 && irafstring[1] == 0)
1477 headswap = 1;
1478 else if (irafstring[0] == 0 && irafstring[1] != 0)
1479 headswap = 0;
1480 else
1481 return (NULL);
1482 }
1483
1484 string = (char *) calloc (nchar+1, 1);
1485 if (string == NULL) {
1486 (void)fprintf(stderr, "IRAF2STR Cannot allocate %d-byte variable\n",
1487 nchar+1);
1488 return (NULL);
1489 }
1490
1491 /* Swap bytes, if requested */
1492 if (headswap)
1493 j = 0;
1494 else
1495 j = 1;
1496
1497 /* Convert appropriate byte of input to output character */
1498 for (i = 0; i < nchar; i++) {
1499 string[i] = irafstring[j];
1500 j = j + 2;
1501 }
1502
1503 return (string);
1504 }
1505
1506
1507 /* IRAFPUTI4 -- Insert 4-byte integer into arbitrary part of IRAF header */
1508
1509 static void
irafputi4(irafheader,offset,inum)1510 irafputi4 (irafheader, offset, inum)
1511
1512 char *irafheader; /* IRAF image header */
1513 int offset; /* Number of bytes to skip before number */
1514 int inum; /* Number to put into header */
1515
1516 {
1517 char *cn, *chead;
1518
1519 chead = irafheader;
1520 cn = (char *) &inum;
1521 if (headswap < 0)
1522 headswap = 0;
1523 if (headswap != machswap()) {
1524 chead[offset+3] = cn[0];
1525 chead[offset+2] = cn[1];
1526 chead[offset+1] = cn[2];
1527 chead[offset] = cn[3];
1528 }
1529 else {
1530 chead[offset] = cn[0];
1531 chead[offset+1] = cn[1];
1532 chead[offset+2] = cn[2];
1533 chead[offset+3] = cn[3];
1534 }
1535 return;
1536 }
1537
1538
1539 /* IRAFPUTR4 -- Insert 4-byte real number into arbitrary part of IRAF header */
1540
1541 static void
irafputr4(irafheader,offset,rnum)1542 irafputr4 (irafheader, offset, rnum)
1543
1544 char *irafheader; /* IRAF image header */
1545 int offset; /* Number of bytes to skip before number */
1546 float rnum; /* Number to put into header */
1547
1548 {
1549 char *cn, *chead;
1550
1551 chead = irafheader;
1552 cn = (char *) &rnum;
1553 if (headswap < 0)
1554 headswap = 0;
1555 if (headswap != machswap()) {
1556 chead[offset+3] = cn[0];
1557 chead[offset+2] = cn[1];
1558 chead[offset+1] = cn[2];
1559 chead[offset] = cn[3];
1560 }
1561 else {
1562 chead[offset] = cn[0];
1563 chead[offset+1] = cn[1];
1564 chead[offset+2] = cn[2];
1565 chead[offset+3] = cn[3];
1566 }
1567 return;
1568 }
1569
1570
1571 /* IRAFPUTC2 -- Insert character string into arbitrary part of v.1 IRAF header */
1572
1573 static void
irafputc2(string,irafheader,offset,nc)1574 irafputc2 (string, irafheader, offset, nc)
1575
1576 char *string; /* String to insert into header */
1577 char *irafheader; /* IRAF image header */
1578 int offset; /* Number of bytes to skip before string */
1579 int nc; /* Maximum number of characters in string */
1580
1581 {
1582 char *irafstring;
1583
1584 irafstring = (char *) calloc (2 * nc, 1);
1585 if (irafstring == NULL) {
1586 (void)fprintf(stderr, "IRAFPUTC2 Cannot allocate %d-byte variable\n",
1587 2 * nc);
1588 }
1589 str2iraf (string, irafstring, nc);
1590 irafputc (irafstring, irafheader, offset, 2*nc);
1591
1592 return;
1593 }
1594
1595
1596 /* IRAFPUTC -- Insert character string into arbitrary part of IRAF header */
1597
1598 static void
irafputc(string,irafheader,offset,nc)1599 irafputc (string, irafheader, offset, nc)
1600
1601 char *string; /* String to insert into header */
1602 char *irafheader; /* IRAF image header */
1603 int offset; /* Number of bytes to skip before string */
1604 int nc; /* Maximum number of characters in string */
1605
1606 {
1607 char *chead;
1608 int i;
1609
1610 chead = irafheader;
1611 for (i = 0; i < nc; i++)
1612 chead[offset+i] = string[i];
1613
1614 return;
1615 }
1616
1617
1618 /* STR2IRAF -- Convert 1-byte/char string to IRAF 2-byte/char string */
1619
1620 static void
str2iraf(string,irafstring,nchar)1621 str2iraf (string, irafstring, nchar)
1622
1623 char *string; /* 1-byte/character string */
1624 char *irafstring; /* IRAF 2-byte/character string */
1625 int nchar; /* Maximum number of characters in IRAF string */
1626 {
1627 int i, j, nc, nbytes;
1628
1629 nc = strlen (string);
1630
1631 /* Fill output string with zeroes */
1632 nbytes = nchar * 2;
1633 for (i = 0; i < nbytes; i++)
1634 irafstring[i] = 0;
1635
1636 /* If swapped, start with first byte of 2-byte characters */
1637 if (headswap)
1638 j = 0;
1639 else
1640 j = 1;
1641
1642 /* Move input characters to appropriate bytes of output */
1643 for (i = 0; i < nchar; i++) {
1644 if (i > nc)
1645 irafstring[j] = 0;
1646 else
1647 irafstring[j] = string[i];
1648 j = j + 2;
1649 }
1650
1651 return;
1652 }
1653
1654
1655 /* IRAFSWAP -- Reverse bytes of any type of vector in place */
1656
1657 static void
irafswap(bitpix,string,nbytes)1658 irafswap (bitpix, string, nbytes)
1659
1660 int bitpix; /* Number of bits per pixel */
1661 /* 16 = short, -16 = unsigned short, 32 = int */
1662 /* -32 = float, -64 = double */
1663 char *string; /* Address of starting point of bytes to swap */
1664 int nbytes; /* Number of bytes to swap */
1665
1666 {
1667 switch (bitpix) {
1668
1669 case 16:
1670 if (nbytes < 2) return;
1671 irafswap2 (string,nbytes);
1672 break;
1673
1674 case 32:
1675 if (nbytes < 4) return;
1676 irafswap4 (string,nbytes);
1677 break;
1678
1679 case -16:
1680 if (nbytes < 2) return;
1681 irafswap2 (string,nbytes);
1682 break;
1683
1684 case -32:
1685 if (nbytes < 4) return;
1686 irafswap4 (string,nbytes);
1687 break;
1688
1689 case -64:
1690 if (nbytes < 8) return;
1691 irafswap8 (string,nbytes);
1692 break;
1693
1694 }
1695 return;
1696 }
1697
1698
1699 /* IRAFSWAP2 -- Swap bytes in string in place */
1700
1701 static void
irafswap2(string,nbytes)1702 irafswap2 (string,nbytes)
1703
1704
1705 char *string; /* Address of starting point of bytes to swap */
1706 int nbytes; /* Number of bytes to swap */
1707
1708 {
1709 char *sbyte, temp, *slast;
1710
1711 slast = string + nbytes;
1712 sbyte = string;
1713 while (sbyte < slast) {
1714 temp = sbyte[0];
1715 sbyte[0] = sbyte[1];
1716 sbyte[1] = temp;
1717 sbyte= sbyte + 2;
1718 }
1719 return;
1720 }
1721
1722
1723 /* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */
1724
1725 static void
irafswap4(string,nbytes)1726 irafswap4 (string,nbytes)
1727
1728 char *string; /* Address of Integer*4 or Real*4 vector */
1729 int nbytes; /* Number of bytes to reverse */
1730
1731 {
1732 char *sbyte, *slast;
1733 char temp0, temp1, temp2, temp3;
1734
1735 slast = string + nbytes;
1736 sbyte = string;
1737 while (sbyte < slast) {
1738 temp3 = sbyte[0];
1739 temp2 = sbyte[1];
1740 temp1 = sbyte[2];
1741 temp0 = sbyte[3];
1742 sbyte[0] = temp0;
1743 sbyte[1] = temp1;
1744 sbyte[2] = temp2;
1745 sbyte[3] = temp3;
1746 sbyte = sbyte + 4;
1747 }
1748
1749 return;
1750 }
1751
1752
1753 /* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */
1754
1755 static void
irafswap8(string,nbytes)1756 irafswap8 (string,nbytes)
1757
1758 char *string; /* Address of Real*8 vector */
1759 int nbytes; /* Number of bytes to reverse */
1760
1761 {
1762 char *sbyte, *slast;
1763 char temp[8];
1764
1765 slast = string + nbytes;
1766 sbyte = string;
1767 while (sbyte < slast) {
1768 temp[7] = sbyte[0];
1769 temp[6] = sbyte[1];
1770 temp[5] = sbyte[2];
1771 temp[4] = sbyte[3];
1772 temp[3] = sbyte[4];
1773 temp[2] = sbyte[5];
1774 temp[1] = sbyte[6];
1775 temp[0] = sbyte[7];
1776 sbyte[0] = temp[0];
1777 sbyte[1] = temp[1];
1778 sbyte[2] = temp[2];
1779 sbyte[3] = temp[3];
1780 sbyte[4] = temp[4];
1781 sbyte[5] = temp[5];
1782 sbyte[6] = temp[6];
1783 sbyte[7] = temp[7];
1784 sbyte = sbyte + 8;
1785 }
1786 return;
1787 }
1788
1789
1790 /* Set flag if machine on which program is executing is not FITS byte order
1791 * ( i.e., if it is an Alpha or PC instead of a Sun ) */
1792
1793 static int
machswap()1794 machswap ()
1795
1796 {
1797 char *ctest;
1798 int itest;
1799
1800 itest = 1;
1801 ctest = (char *)&itest;
1802 if (*ctest)
1803 return (1);
1804 else
1805 return (0);
1806 }
1807
1808
1809 /* ISIRAF -- return 1 if IRAF imh file, else 0 */
1810
1811 int
isiraf(filename)1812 isiraf (filename)
1813
1814 char *filename; /* Name of file for which to find size */
1815 {
1816 if (strchr (filename, '='))
1817 return (0);
1818 else if (strsrch (filename, ".imh"))
1819 return (1);
1820 else
1821 return (0);
1822 }
1823
1824
1825 /* IRAFSIZE -- return size of file in bytes */
1826
1827 static int
irafsize(diskfile)1828 irafsize (diskfile)
1829
1830 FILE *diskfile; /* Descriptor of file for which to find size */
1831 {
1832 long filesize;
1833 long offset;
1834
1835 offset = (long) 0;
1836
1837 /* Move to end of the file */
1838 if (fseek (diskfile, offset, SEEK_END) == 0) {
1839
1840 /* Position is the size of the file */
1841 filesize = ftell (diskfile);
1842
1843 /* Move file pointer back tot he start of the file */
1844 fseek (diskfile, offset, SEEK_SET);
1845 }
1846
1847 else
1848 filesize = -1;
1849
1850 return (filesize);
1851 }
1852
1853 /* Feb 15 1996 New file
1854 * Apr 10 1996 Add more documentation
1855 * Apr 17 1996 Print error message on open failure
1856 * Jun 5 1996 Add byte swapping (reversal); use streams
1857 * Jun 10 1996 Make fixes after running lint
1858 * Jun 12 1996 Use IMSWAP subroutines instead of local ones
1859 * Jul 3 1996 Go back to using local IRAFSWAP subroutines
1860 * Jul 3 1996 Write to pixel file from FITS header
1861 * Jul 10 1996 Allocate all headers
1862 * Aug 13 1996 Add unistd.h to include list
1863 * Aug 26 1996 Allow 1-d images; fix comments; fix arguments after lint
1864 * Aug 26 1996 Add IRAF header lingth argument to IRAFWIMAGE and IRAFWHEAD
1865 * Aug 28 1996 Clean up code in IRAF2FITS
1866 * Aug 30 1996 Use write instead of fwrite
1867 * Sep 4 1996 Fix write mode bug
1868 * Oct 15 1996 Drop unused variables
1869 * Oct 17 1996 Minor fix after lint; cast arguments to STR2IRAF
1870 *
1871 * May 15 1997 Fix returned header length in IRAF2FITS
1872 * Dec 19 1997 Add IRAF version 2 .imh files
1873 *
1874 * Jan 2 1998 Allow uneven length of user parameter lines in IRAF headers
1875 * Jan 6 1998 Fix output of imh2 headers; allow newlines in imh1 headers
1876 * Jan 14 1998 Handle byte reversing correctly
1877 * Apr 17 1998 Add new IRAF data types unsigned char and unsigned short
1878 * Apr 30 1998 Fix error return if illegal data type after Allan Brighton
1879 * May 15 1998 Delete header keywords used for IRAF binary values
1880 * May 15 1998 Fix bug so FITS OBJECT is put into IRAF title
1881 * May 26 1998 Fix bug in fits2iraf keeping track of end of header
1882 * May 27 1998 Include fitsio.h instead of fitshead.h
1883 * Jun 4 1998 Write comments into header for converted IRAF binary values
1884 * Jun 4 1998 Pad FITS strings to 8 character minimum
1885 * Jul 24 1998 Write header file length to IRAF header file
1886 * Jul 27 1998 Print error messages to stderr for all failed malloc's
1887 * Jul 27 1998 Fix bug padding FITS header with spaces in iraf2fits
1888 * Jul 27 1998 Write modification time to IRAF header file
1889 * Aug 6 1998 Change fitsio.h to fitsfile.h; imhio.c to imhfile.c
1890 * Oct 1 1998 Set irafswap flag only once per file
1891 * Oct 5 1998 Add subroutines irafsize() and isiraf()
1892 * Nov 16 1998 Fix byte-swap checking
1893 *
1894 * Jan 27 1999 Read and write all of 3D image if one dimension is =1
1895 * Jul 13 1999 Improve error messages; change irafsize() argument to fd
1896 * Sep 22 1999 Don't copy OBJECT keyword from .imh file; use binary title
1897 * Oct 14 1999 Set FITS header length
1898 * Oct 20 1999 Allocate 5000 extra bytes for IRAF header
1899 * Nov 2 1999 Fix getclocktime() to use only time.h subroutines
1900 * Nov 2 1999 Add modification date and time to FITS header in iraf2fits()
1901 * Nov 24 1999 Delete HEADSWAP, IMHVER, DATE-MOD from header before writing
1902 * Nov 29 1999 Delete PIXSWAP, IRAF-MIN, IRAF-MAX from header before writing
1903 *
1904 * Jan 13 2000 Fix bug which dropped characters in iraf2fits()
1905 * Feb 3 2000 Declare timezone long, not time_t; drop unused variable
1906 * Mar 7 2000 Add more code to keep pixel file path short
1907 * Mar 10 2000 Fix bugs when writing .imh file headers
1908 * Mar 21 2000 Change computation of IRAF time tags to use only data structure
1909 * Mar 22 2000 Move IRAF time tag computation to lt2tsi() in dateutil.c
1910 * Mar 24 2000 Use Unix file update time if none in header
1911 * Mar 27 2000 Use hputm() to save file paths up to 256 characters
1912 * Mar 27 2000 Write filename comments after 1st keyword with short value
1913 * Mar 27 2000 Allocate pixel file name in same_path to imh2 length
1914 * Mar 29 2000 Add space after last linefeed of header in fits2iraf()
1915 * Apr 28 2000 Dimension pixname in irafwimage()
1916 * May 1 2000 Fix code for updating pixel file name with HDR$ in fits2iraf()
1917 * Jun 2 2000 Drop unused variables in fits2iraf() after lint
1918 * Jun 12 2000 If pixel filename has no / or $, use same path as header file
1919 * Sep 6 2000 Use header directory if pixel file not found at its pathname
1920 *
1921 * Jan 11 2001 Print all messages to stderr
1922 * Aug 24 2001 In isiraf(), return 0 if argument contains an equal sign
1923 *
1924 * Apr 8 2002 Fix bug in error message for unidentified nbits in fits2iraf()
1925 *
1926 * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern)
1927 * Oct 31 2003 Read image only in irafrimage() if physical dimension > image dim.
1928 * Nov 3 2003 Set NAXISi to image, not physical dimensions in iraf2fits()
1929 *
1930 * Jun 13 2005 Drop trailing spaces on pixel file name
1931 *
1932 * Jun 20 2006 Initialize uninitialized variables
1933 *
1934 * Jan 4 2007 Change hputr4() calls to send pointer to value
1935 * Jan 8 2007 Drop unused variable nbx in irafrimage()
1936 * Jan 8 2007 Align header and image buffers properly by 4 and by BITPIX
1937 *
1938 * May 20 2011 Free newpixname, not pixname in irafwimage()
1939 *
1940 * Mar 27 2012 Fix pixname's appending to newpixname to avoid overflow
1941 */
1942