/*** File imhfile.c *** March 27, 2012 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2012 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: imhfile.c (IRAF .imh image file reading and writing) * Purpose: Read and write IRAF image files (and translate headers) * Subroutine: check_immagic (irafheader, teststring ) * Verify that file is valid IRAF imhdr or impix * Subroutine: irafrhead (filename, lfhead, fitsheader, lihead) * Read IRAF image header * Subroutine: irafrimage (fitsheader) * Read IRAF image pixels (call after irafrhead) * Subroutine: same_path (pixname, hdrname) * Put filename and header path together * Subroutine: iraf2fits (hdrname, irafheader, nbiraf, nbfits) * Convert IRAF image header to FITS image header * Subroutine: irafwhead (hdrname, irafheader, fitsheader) * Write IRAF header file * Subroutine: irafwimage (hdrname, irafheader, fitsheader, image ) * Write IRAF image and header files * Subroutine: fits2iraf (fitsheader, irafheader) * Convert FITS image header to IRAF image header * Subroutine: irafgeti4 (irafheader, offset) * Get 4-byte integer from arbitrary part of IRAF header * Subroutine: irafgetc2 (irafheader, offset) * Get character string from arbitrary part of IRAF v.1 header * Subroutine: irafgetc (irafheader, offset) * Get character string from arbitrary part of IRAF header * Subroutine: iraf2str (irafstring, nchar) * Convert 2-byte/char IRAF string to 1-byte/char string * Subroutine: str2iraf (string, irafstring, nchar) * Convert 1-byte/char string to IRAF 2-byte/char string * Subroutine: irafswap (bitpix,string,nbytes) * Swap bytes in string in place, with FITS bits/pixel code * Subroutine: irafswap2 (string,nbytes) * Swap bytes in string in place * Subroutine irafswap4 (string,nbytes) * Reverse bytes of Integer*4 or Real*4 vector in place * Subroutine irafswap8 (string,nbytes) * Reverse bytes of Real*8 vector in place * Subroutine irafsize (filename) * Return length of file in bytes * Subroutine isiraf (filename) * Return 1 if IRAF .imh file, else 0 * Copyright: 2000 Smithsonian Astrophysical Observatory * You may do anything you like with this file except remove * this copyright. The Smithsonian Astrophysical Observatory * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */ #include /* define stderr, FD, and NULL */ #include #include #include #include #include #include #include "fitsfile.h" /* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */ #define SZ_IMPIXFILE 79 /* name of pixel storage file */ #define SZ_IMHDRFILE 79 /* length of header storage file */ #define SZ_IMTITLE 79 /* image title string */ #define LEN_IMHDR 2052 /* length of std header */ /* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */ #define SZ_IM2PIXFILE 255 /* name of pixel storage file */ #define SZ_IM2HDRFILE 255 /* name of header storage file */ #define SZ_IM2TITLE 383 /* image title string */ #define LEN_IM2HDR 2046 /* length of std header */ /* Offsets into header in bytes for parameters in IRAF version 1 images */ #define IM_HDRLEN 12 /* Length of header in 4-byte ints */ #define IM_PIXTYPE 16 /* Datatype of the pixels */ #define IM_NDIM 20 /* Number of dimensions */ #define IM_LEN 24 /* Length (as stored) */ #define IM_PHYSLEN 52 /* Physical length (as stored) */ #define IM_PIXOFF 88 /* Offset of the pixels */ #define IM_CTIME 108 /* Time of image creation */ #define IM_MTIME 112 /* Time of last modification */ #define IM_LIMTIME 116 /* Time of min,max computation */ #define IM_MAX 120 /* Maximum pixel value */ #define IM_MIN 124 /* Maximum pixel value */ #define IM_PIXFILE 412 /* Name of pixel storage file */ #define IM_HDRFILE 572 /* Name of header storage file */ #define IM_TITLE 732 /* Image name string */ /* Offsets into header in bytes for parameters in IRAF version 2 images */ #define IM2_HDRLEN 6 /* Length of header in 4-byte ints */ #define IM2_PIXTYPE 10 /* Datatype of the pixels */ #define IM2_SWAPPED 14 /* Pixels are byte swapped */ #define IM2_NDIM 18 /* Number of dimensions */ #define IM2_LEN 22 /* Length (as stored) */ #define IM2_PHYSLEN 50 /* Physical length (as stored) */ #define IM2_PIXOFF 86 /* Offset of the pixels */ #define IM2_CTIME 106 /* Time of image creation */ #define IM2_MTIME 110 /* Time of last modification */ #define IM2_LIMTIME 114 /* Time of min,max computation */ #define IM2_MAX 118 /* Maximum pixel value */ #define IM2_MIN 122 /* Maximum pixel value */ #define IM2_PIXFILE 126 /* Name of pixel storage file */ #define IM2_HDRFILE 382 /* Name of header storage file */ #define IM2_TITLE 638 /* Image name string */ /* Codes from iraf/unix/hlib/iraf.h */ #define TY_CHAR 2 #define TY_SHORT 3 #define TY_INT 4 #define TY_LONG 5 #define TY_REAL 6 #define TY_DOUBLE 7 #define TY_COMPLEX 8 #define TY_POINTER 9 #define TY_STRUCT 10 #define TY_USHORT 11 #define TY_UBYTE 12 #define LEN_IRAFHDR 25000 #define LEN_PIXHDR 1024 #define LEN_FITSHDR 11520 int check_immagic(); int irafgeti4(); float irafgetr4(); char *irafgetc2(); char *irafgetc(); char *iraf2str(); static char *same_path(); static void irafputr4(); static void irafputi4(); static void irafputc2(); static void irafputc(); static void str2iraf(); static int headswap=-1; /* =1 to swap data bytes of foreign IRAF file */ static void irafswap(); static void irafswap2(); static void irafswap4(); static void irafswap8(); int head_version (); int pix_version (); int irafncmp (); static int machswap(); static int irafsize(); #define SECONDS_1970_TO_1980 315532800L /* Subroutine: irafrhead * Purpose: Open and read the iraf .imh file, translating it to FITS, too. * Returns: NULL if failure, else pointer to IRAF .imh image header * Notes: The imhdr format is defined in iraf/lib/imhdr.h, some of * which defines or mimicked, above. */ char * irafrhead (filename, lihead) char *filename; /* Name of IRAF header file */ int *lihead; /* Length of IRAF image header in bytes (returned) */ { FILE *fd; int nbr; char *irafheader; int nbhead, nbytes; int imhver; headswap = -1; *lihead = 0; /* open the image header file */ fd = fopen (filename, "rb"); if (fd == NULL) { fprintf (stderr, "IRAFRHEAD: cannot open file %s to read\n", filename); return (NULL); } /* Find size of image header file */ if ((nbhead = irafsize (fd)) <= 0) { fprintf (stderr, "IRAFRHEAD: cannot read file %s, size = %d\n", filename, nbhead); return (NULL); } /* allocate initial sized buffer */ nbytes = nbhead + 5000; irafheader = (char *) calloc (nbytes/4, 4); if (irafheader == NULL) { (void)fprintf(stderr, "IRAFRHEAD Cannot allocate %d-byte header\n", nbytes); return (NULL); } *lihead = nbytes; /* Read IRAF header */ nbr = fread (irafheader, 1, nbhead, fd); fclose (fd); /* Reject if header less than minimum length */ if (nbr < LEN_PIXHDR) { (void)fprintf(stderr, "IRAFRHEAD header file %s: %d / %d bytes read.\n", filename,nbr,LEN_PIXHDR); free (irafheader); return (NULL); } /* Check header magic word */ imhver = head_version (irafheader); if (imhver < 1) { free (irafheader); (void)fprintf(stderr, "IRAFRHEAD: %s is not a valid IRAF image header\n", filename); return(NULL); } /* check number of image dimensions if (imhver == 2) ndim = irafgeti4 (irafheader, IM2_NDIM]) else ndim = irafgeti4 (irafheader, IM_NDIM]) if (ndim < 2) { free (irafheader); (void)fprintf(stderr, "File %s does not contain 2d image\n", filename); return (NULL); } */ return (irafheader); } char * irafrimage (fitsheader) char *fitsheader; /* FITS image header (filled) */ { FILE *fd; char *bang; int naxis, naxis1, naxis2, naxis3, npaxis1, npaxis2,bitpix, bytepix, pixswap, i; char *image; int nbr, nbimage, nbaxis, nbl, nbdiff, lpname; char *pixheader; char *linebuff, *pixchar; int imhver, lpixhead, len; char pixname[SZ_IM2PIXFILE+1]; char newpixname[SZ_IM2HDRFILE+1]; /* Convert pixel file name to character string */ hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname); /* Drop trailing spaces */ lpname = strlen (pixname); pixchar = pixname + lpname - 1; while (*pixchar == ' ') *pixchar = (char) 0; hgeti4 (fitsheader, "PIXOFF", &lpixhead); /* Open pixel file, ignoring machine name if present */ if ((bang = strchr (pixname, '!')) != NULL ) fd = fopen (bang + 1, "rb"); else fd = fopen (pixname, "rb"); /* If not at pathname in header, try same directory as header file */ if (!fd) { hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, newpixname); len = strlen (newpixname); newpixname[len-3] = 'p'; newpixname[len-2] = 'i'; newpixname[len-1] = 'x'; fd = fopen (newpixname, "rb"); } /* Print error message and exit if pixel file is not found */ if (!fd) { (void)fprintf(stderr, "IRAFRIMAGE: Cannot open IRAF pixel file %s\n", pixname); return (NULL); } /* Read pixel header */ pixheader = (char *) calloc (lpixhead/4, 4); if (pixheader == NULL) { (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte pixel header\n", lpixhead); return (NULL); } nbr = fread (pixheader, 1, lpixhead, fd); /* Check size of pixel header */ if (nbr < lpixhead) { (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n", pixname,nbr,LEN_PIXHDR); free (pixheader); fclose (fd); return (NULL); } /* check pixel header magic word */ imhver = pix_version (pixheader); if (imhver < 1) { (void)fprintf(stderr, "File %s not valid IRAF pixel file.\n", pixname); free (pixheader); fclose (fd); return(NULL); } free (pixheader); /* Find number of bytes to read */ hgeti4 (fitsheader,"NAXIS",&naxis); hgeti4 (fitsheader,"NAXIS1",&naxis1); hgeti4 (fitsheader,"NAXIS2",&naxis2); hgeti4 (fitsheader,"NPAXIS1",&npaxis1); hgeti4 (fitsheader,"NPAXIS2",&npaxis2); hgeti4 (fitsheader,"BITPIX",&bitpix); if (bitpix < 0) bytepix = -bitpix / 8; else bytepix = bitpix / 8; /* If either dimension is one and image is 3-D, read all three dimensions */ if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) { hgeti4 (fitsheader,"NAXIS3",&naxis3); nbimage = naxis1 * naxis2 * naxis3 * bytepix; } else { nbimage = naxis1 * naxis2 * bytepix; naxis3 = 1; } if (bytepix > 4) image = (char *) calloc (nbimage/8, 8); else if (bytepix > 2) image = (char *) calloc (nbimage/4, 4); else if (bytepix > 1) image = (char *) calloc (nbimage/2, 2); else image = (char *) calloc (nbimage, 1); if (image == NULL) { (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte image buffer\n", nbimage); return (NULL); } /* Read IRAF image all at once if physical and image dimensions are the same */ if (npaxis1 == naxis1) nbr = fread (image, 1, nbimage, fd); /* Read IRAF image one line at a time if physical and image dimensions differ */ else { nbdiff = (npaxis1 - naxis1) * bytepix; nbaxis = naxis1 * bytepix; linebuff = image; nbr = 0; if (naxis2 == 1 && naxis3 > 1) naxis2 = naxis3; for (i = 0; i < naxis2; i++) { nbl = fread (linebuff, 1, nbaxis, fd); nbr = nbr + nbl; (void) fseek (fd, nbdiff, SEEK_CUR); linebuff = linebuff + nbaxis; } } fclose (fd); /* Check size of image */ if (nbr < nbimage) { (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n", pixname,nbr,nbimage); free (image); return (NULL); } /* Byte-reverse image, if necessary */ pixswap = 0; hgetl (fitsheader, "PIXSWAP", &pixswap); if (pixswap) irafswap (bitpix, image, nbimage); return (image); } /* Return IRAF image format version number from magic word in IRAF header*/ int head_version (irafheader) char *irafheader; /* IRAF image header from file */ { /* Check header file magic word */ if (irafncmp (irafheader, "imhdr", 5) != 0 ) { if (strncmp (irafheader, "imhv2", 5) != 0) return (0); else return (2); } else return (1); } /* Return IRAF image format version number from magic word in IRAF pixel file */ int pix_version (irafheader) char *irafheader; /* IRAF image header from file */ { /* Check pixel file header magic word */ if (irafncmp (irafheader, "impix", 5) != 0) { if (strncmp (irafheader, "impv2", 5) != 0) return (0); else return (2); } else return (1); } /* Verify that file is valid IRAF imhdr or impix by checking first 5 chars * Returns: 0 on success, 1 on failure */ int irafncmp (irafheader, teststring, nc) char *irafheader; /* IRAF image header from file */ char *teststring; /* C character string to compare */ int nc; /* Number of characters to compate */ { char *line; headswap = -1; if ((line = iraf2str (irafheader, nc)) == NULL) return (1); if (strncmp (line, teststring, nc) == 0) { free (line); return (0); } else { free (line); return (1); } } /* Convert IRAF image header to FITS image header, returning FITS header */ char * iraf2fits (hdrname, irafheader, nbiraf, nbfits) char *hdrname; /* IRAF header file name (may be path) */ char *irafheader; /* IRAF image header */ int nbiraf; /* Number of bytes in IRAF header */ int *nbfits; /* Number of bytes in FITS header (returned) */ { char *objname; /* object name from FITS file */ int lstr, i, j, k, ib, nax, nbits, nl; int lname = 0; char *pixname, *newpixname, *bang, *chead; char *fitsheader; int nblock, nlines; char *fhead, *fhead1, *fp, endline[81]; char irafchar; char fitsline[81]; char *dstring; int pixtype; int imhver, n, imu, pixoff, impixoff, immax, immin, imtime; int imndim, imlen, imphyslen, impixtype, pixswap, hpixswap, mtime; float rmax, rmin; headswap = -1; /* Set up last line of FITS header */ (void)strncpy (endline,"END", 3); for (i = 3; i < 80; i++) endline[i] = ' '; endline[80] = 0; /* Check header magic word */ imhver = head_version (irafheader); if (imhver < 1) { (void)fprintf(stderr, "File %s not valid IRAF image header\n", hdrname); return(NULL); } if (imhver == 2) { nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81); imndim = IM2_NDIM; imlen = IM2_LEN; imphyslen = IM2_PHYSLEN; impixtype = IM2_PIXTYPE; impixoff = IM2_PIXOFF; imtime = IM2_MTIME; immax = IM2_MAX; immin = IM2_MIN; } else { nlines = 24 + ((nbiraf - LEN_IMHDR) / 162); imndim = IM_NDIM; imlen = IM_LEN; imphyslen = IM_PHYSLEN; impixtype = IM_PIXTYPE; impixoff = IM_PIXOFF; imtime = IM_MTIME; immax = IM_MAX; immin = IM_MIN; } /* Initialize FITS header */ nblock = (nlines * 80) / 2880; *nbfits = (nblock + 5) * 2880 + 4; fitsheader = (char *) calloc (*nbfits, 1); if (fitsheader == NULL) { (void)fprintf(stderr, "IRAF2FITS Cannot allocate %d-byte FITS header\n", *nbfits); return (NULL); } hlength (fitsheader, *nbfits); fhead = fitsheader; (void)strncpy (fitsheader, endline, 80); hputl (fitsheader, "SIMPLE", 1); fhead = fhead + 80; /* Set pixel size in FITS header */ pixtype = irafgeti4 (irafheader, impixtype); switch (pixtype) { case TY_CHAR: nbits = 8; break; case TY_UBYTE: nbits = 8; break; case TY_SHORT: nbits = 16; break; case TY_USHORT: nbits = -16; break; case TY_INT: case TY_LONG: nbits = 32; break; case TY_REAL: nbits = -32; break; case TY_DOUBLE: nbits = -64; break; default: (void)fprintf(stderr,"Unsupported data type: %d\n", pixtype); return (NULL); } hputi4 (fitsheader,"BITPIX",nbits); hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type"); fhead = fhead + 80; /* Set image dimensions in FITS header */ nax = irafgeti4 (irafheader, imndim); hputi4 (fitsheader,"NAXIS",nax); hputcom (fitsheader,"NAXIS", "IRAF .imh naxis"); fhead = fhead + 80; n = irafgeti4 (irafheader, imlen); hputi4 (fitsheader, "NAXIS1", n); hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]"); fhead = fhead + 80; if (nax > 1) { n = irafgeti4 (irafheader, imlen+4); hputi4 (fitsheader, "NAXIS2", n); hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]"); } else hputi4 (fitsheader, "NAXIS2", 1); hputcom (fitsheader,"NAXIS2", "IRAF .imh naxis[2]"); fhead = fhead + 80; if (nax > 2) { n = irafgeti4 (irafheader, imlen+8); hputi4 (fitsheader, "NAXIS3", n); hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]"); fhead = fhead + 80; } if (nax > 3) { n = irafgeti4 (irafheader, imlen+12); hputi4 (fitsheader, "NAXIS4", n); hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]"); fhead = fhead + 80; } /* Set object name in FITS header */ if (imhver == 2) objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE); else objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE); if ((lstr = strlen (objname)) < 8) { for (i = lstr; i < 8; i++) objname[i] = ' '; objname[8] = 0; } hputs (fitsheader,"OBJECT",objname); hputcom (fitsheader,"OBJECT", "IRAF .imh title"); free (objname); fhead = fhead + 80; /* Save physical axis lengths so image file can be read */ n = irafgeti4 (irafheader, imphyslen); hputi4 (fitsheader, "NPAXIS1", n); hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]"); fhead = fhead + 80; if (nax > 1) { n = irafgeti4 (irafheader, imphyslen+4); hputi4 (fitsheader, "NPAXIS2", n); hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]"); fhead = fhead + 80; } if (nax > 2) { n = irafgeti4 (irafheader, imphyslen+8); hputi4 (fitsheader, "NPAXIS3", n); hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]"); fhead = fhead + 80; } if (nax > 3) { n = irafgeti4 (irafheader, imphyslen+12); hputi4 (fitsheader, "NPAXIS4", n); hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]"); fhead = fhead + 80; } /* Save image minimum and maximum in header */ rmax = irafgetr4 (irafheader, immax); rmin = irafgetr4 (irafheader, immin); if (rmin != rmax) { hputr4 (fitsheader, "IRAFMIN", &rmin); fhead = fhead + 80; hputcom (fitsheader,"IRAFMIN", "IRAF .imh minimum"); hputr4 (fitsheader, "IRAFMAX", &rmax); hputcom (fitsheader,"IRAFMAX", "IRAF .imh maximum"); fhead = fhead + 80; } /* Save image header filename in header */ nl = hputm (fitsheader,"IMHFIL",hdrname); if (nl > 0) { lname = strlen (hdrname); strcpy (fitsline, "IRAF header file name"); if (lname < 43) hputcom (fitsheader,"IMHFIL_1", fitsline); else if (lname > 67 && lname < 110) hputcom (fitsheader,"IMHFIL_2", fitsline); else if (lname > 134 && lname < 177) hputcom (fitsheader,"IMHFIL_3", fitsline); } if (nl > 0) fhead = fhead + (nl * 80); /* Save image pixel file pathname in header */ if (imhver == 2) pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); if (strncmp(pixname, "HDR", 3) == 0 ) { newpixname = same_path (pixname, hdrname); free (pixname); pixname = newpixname; } if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { newpixname = same_path (pixname, hdrname); free (pixname); pixname = newpixname; } if ((bang = strchr (pixname, '!')) != NULL ) nl = hputm (fitsheader,"PIXFIL",bang+1); else nl = hputm (fitsheader,"PIXFIL",pixname); free (pixname); if (nl > 0) { strcpy (fitsline, "IRAF .pix pixel file"); if (lname < 43) hputcom (fitsheader,"PIXFIL_1", fitsline); else if (lname > 67 && lname < 110) hputcom (fitsheader,"PIXFIL_2", fitsline); else if (lname > 134 && lname < 177) hputcom (fitsheader,"PIXFIL_3", fitsline); } if (nl > 0) fhead = fhead + (nl * 80); /* Save image offset from star of pixel file */ pixoff = irafgeti4 (irafheader, impixoff); pixoff = (pixoff - 1) * 2; hputi4 (fitsheader, "PIXOFF", pixoff); hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)"); fhead = fhead + 80; /* Save IRAF file format version in header */ hputi4 (fitsheader,"IMHVER",imhver); hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)"); fhead = fhead + 80; /* Set flag if header numbers are byte-reversed on this machine */ if (machswap() != headswap) hputl (fitsheader, "HEADSWAP", 1); else hputl (fitsheader, "HEADSWAP", 0); hputcom (fitsheader,"HEADSWAP", "IRAF header, FITS byte orders differ if T"); fhead = fhead + 80; /* Set flag if image pixels are byte-reversed on this machine */ if (imhver == 2) { hpixswap = irafgeti4 (irafheader, IM2_SWAPPED); if (headswap && !hpixswap) pixswap = 1; else if (!headswap && hpixswap) pixswap = 1; else pixswap = 0; } else pixswap = headswap; if (machswap() != pixswap) hputl (fitsheader, "PIXSWAP", 1); else hputl (fitsheader, "PIXSWAP", 0); hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T"); fhead = fhead + 80; /* Read modification time */ mtime = irafgeti4 (irafheader, imtime); if (mtime == 0) dstring = lt2fd (); else dstring = tsi2fd (mtime); hputs (fitsheader, "DATE-MOD", dstring); hputcom (fitsheader,"DATE-MOD", "Date of latest file modification"); free (dstring); fhead = fhead + 80; /* Add user portion of IRAF header to FITS header */ fitsline[80] = 0; if (imhver == 2) { imu = LEN_IM2HDR; chead = irafheader; j = 0; for (k = 0; k < 80; k++) fitsline[k] = ' '; for (i = imu; i < nbiraf; i++) { irafchar = chead[i]; if (irafchar == 0) break; else if (irafchar == 10) { (void)strncpy (fhead, fitsline, 80); /* fprintf (stderr,"%80s\n",fitsline); */ if (strncmp (fitsline, "OBJECT ", 7) != 0) { fhead = fhead + 80; } for (k = 0; k < 80; k++) fitsline[k] = ' '; j = 0; } else { if (j > 80) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); /* fprintf (stderr,"%80s\n",fitsline); */ j = 9; fhead = fhead + 80; } for (k = 0; k < 80; k++) fitsline[k] = ' '; } if (irafchar > 32 && irafchar < 127) fitsline[j] = irafchar; j++; } } } else { imu = LEN_IMHDR; chead = irafheader; if (headswap == 1) ib = 0; else ib = 1; for (k = 0; k < 80; k++) fitsline[k] = ' '; j = 0; for (i = imu; i < nbiraf; i=i+2) { irafchar = chead[i+ib]; if (irafchar == 0) break; else if (irafchar == 10) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); fhead = fhead + 80; } /* fprintf (stderr,"%80s\n",fitsline); */ j = 0; for (k = 0; k < 80; k++) fitsline[k] = ' '; } else { if (j > 80) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); j = 9; fhead = fhead + 80; } /* fprintf (stderr,"%80s\n",fitsline); */ for (k = 0; k < 80; k++) fitsline[k] = ' '; } if (irafchar > 32 && irafchar < 127) fitsline[j] = irafchar; j++; } } } /* Add END to last line */ (void)strncpy (fhead, endline, 80); /* Find end of last 2880-byte block of header */ fhead = ksearch (fitsheader, "END") + 80; nblock = *nbfits / 2880; fhead1 = fitsheader + (nblock * 2880); /* Pad rest of header with spaces */ strncpy (endline," ",3); for (fp = fhead; fp < fhead1; fp = fp + 80) { (void)strncpy (fp, endline,80); } return (fitsheader); } int irafwhead (hdrname, lhead, irafheader, fitsheader) char *hdrname; /* Name of IRAF header file */ int lhead; /* Length of IRAF header */ char *irafheader; /* IRAF header */ char *fitsheader; /* FITS image header */ { int fd; int nbw, nbhead, lphead, pixswap; /* Get rid of redundant header information */ hgeti4 (fitsheader, "PIXOFF", &lphead); hgeti4 (fitsheader, "PIXSWAP", &pixswap); /* Write IRAF header file */ /* Convert FITS header to IRAF header */ irafheader = fits2iraf (fitsheader, irafheader, lhead, &nbhead); if (irafheader == NULL) { fprintf (stderr, "IRAFWIMAGE: file %s header error\n", hdrname); return (-1); } /* Open the output file */ if (!access (hdrname, 0)) { fd = open (hdrname, O_WRONLY); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", hdrname); return (0); } } else { fd = open (hdrname, O_RDWR+O_CREAT, 0666); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", hdrname); return (0); } } /* Write IRAF header to disk file */ nbw = write (fd, irafheader, nbhead); (void) ftruncate (fd, nbhead); close (fd); if (nbw < nbhead) { (void)fprintf(stderr, "IRAF header file %s: %d / %d bytes written.\n", hdrname, nbw, nbhead); return (-1); } return (nbw); } /* IRAFWIMAGE -- write IRAF .imh header file and .pix image file * No matter what the input, this always writes in the local byte order */ int irafwimage (hdrname, lhead, irafheader, fitsheader, image ) char *hdrname; /* Name of IRAF header file */ int lhead; /* Length of IRAF header */ char *irafheader; /* IRAF header */ char *fitsheader; /* FITS image header */ char *image; /* IRAF image */ { int fd; char *bang; int nbw, bytepix, bitpix, naxis, naxis1, naxis2, nbimage, lphead; char *pixn, *newpixname; char pixname[SZ_IM2PIXFILE+1]; int imhver, pixswap; hgeti4 (fitsheader, "IMHVER", &imhver); if (!hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname)) { if (imhver == 2) pixn = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else pixn = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); if (strncmp(pixn, "HDR", 3) == 0 ) { newpixname = same_path (pixn, hdrname); strcpy (pixname, newpixname); free (newpixname); } else { if ((bang = strchr (pixn, '!')) != NULL ) strcpy (pixname, bang+1); else strcpy (pixname, pixn); } free (pixn); } /* Find number of bytes to write */ hgeti4 (fitsheader,"NAXIS",&naxis); hgeti4 (fitsheader,"NAXIS1",&naxis1); hgeti4 (fitsheader,"NAXIS2",&naxis2); hgeti4 (fitsheader,"BITPIX",&bitpix); if (bitpix < 0) bytepix = -bitpix / 8; else bytepix = bitpix / 8; /* If either dimension is one and image is 3-D, read all three dimensions */ if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) { int naxis3; hgeti4 (fitsheader,"NAXIS3",&naxis3); nbimage = naxis1 * naxis2 * naxis3 * bytepix; } else nbimage = naxis1 * naxis2 * bytepix; /* Read information about pixel file from header */ hgeti4 (fitsheader, "PIXOFF", &lphead); hgeti4 (fitsheader, "PIXSWAP", &pixswap); /* Write IRAF header file */ if (irafwhead (hdrname, lhead, irafheader, fitsheader)) return (0); /* Open the output file */ if (!access (pixname, 0)) { fd = open (pixname, O_WRONLY); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", pixname); return (0); } } else { fd = open (pixname, O_RDWR+O_CREAT, 0666); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", pixname); return (0); } } /* Write header to IRAF pixel file */ if (imhver == 2) irafputc ("impv2", irafheader, 0, 5); else irafputc2 ("impix", irafheader, 0, 5); nbw = write (fd, irafheader, lphead); /* Byte-reverse image, if necessary */ if (pixswap) irafswap (bitpix, image, nbimage); /* Write data to IRAF pixel file */ nbw = write (fd, image, nbimage); close (fd); return (nbw); } /* Put filename and header path together */ static char * same_path (pixname, hdrname) char *pixname; /* IRAF pixel file pathname */ char *hdrname; /* IRAF image header file pathname */ { int len, plen; char *newpixname; newpixname = (char *) calloc (SZ_IM2PIXFILE, 1); /* Pixel file is in same directory as header */ if (strncmp(pixname, "HDR$", 4) == 0 ) { (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); /* find the end of the pathname */ len = strlen (newpixname); #ifndef VMS while( (len > 0) && (newpixname[len-1] != '/') ) #else while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) #endif len--; /* add name */ newpixname[len] = '\0'; plen = strlen (pixname) - 4; if (len + plen > SZ_IM2PIXFILE) (void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE - len); else (void)strncat (newpixname, &pixname[4], plen); } /* Bare pixel file with no path is assumed to be same as HDR$filename */ else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); /* find the end of the pathname */ len = strlen (newpixname); #ifndef VMS while( (len > 0) && (newpixname[len-1] != '/') ) #else while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) #endif len--; /* add name */ newpixname[len] = '\0'; (void)strncat (newpixname, pixname, SZ_IM2PIXFILE); } /* Pixel file has same name as header file, but with .pix extension */ else if (strncmp (pixname, "HDR", 3) == 0) { /* load entire header name string into name buffer */ (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); len = strlen (newpixname); newpixname[len-3] = 'p'; newpixname[len-2] = 'i'; newpixname[len-1] = 'x'; } return (newpixname); } /* Convert FITS image header to IRAF image header, returning IRAF header */ /* No matter what the input, this always writes in the local byte order */ char * fits2iraf (fitsheader, irafheader, nbhead, nbiraf) char *fitsheader; /* FITS image header */ char *irafheader; /* IRAF image header (returned updated) */ int nbhead; /* Length of IRAF header */ int *nbiraf; /* Length of returned IRAF header */ { int i, n, pixoff, lhdrdir; short *irafp, *irafs, *irafu; char *iraf2u, *iraf2p, *filename, *hdrdir; char *fitsend, *fitsp, pixfile[SZ_IM2PIXFILE], hdrfile[SZ_IM2HDRFILE]; char title[SZ_IM2TITLE], temp[80]; int nax, nlfits, imhver, nbits, pixtype, hdrlength, mtime; int imndim, imlen, imphyslen, impixtype, imhlen, imtime, immax, immin; float rmax, rmin; hgeti4 (fitsheader, "IMHVER", &imhver); hdel (fitsheader, "IMHVER"); hdel (fitsheader, "IMHVER"); hgetl (fitsheader, "HEADSWAP", &headswap); hdel (fitsheader, "HEADSWAP"); hdel (fitsheader, "HEADSWAP"); if (imhver == 2) { imhlen = IM2_HDRLEN; imndim = IM2_NDIM; imlen = IM2_LEN; imtime = IM2_MTIME; imphyslen = IM2_PHYSLEN; impixtype = IM2_PIXTYPE; immax = IM2_MAX; immin = IM2_MIN; } else { imhlen = IM_HDRLEN; imndim = IM_NDIM; imlen = IM_LEN; imtime = IM_MTIME; imphyslen = IM_PHYSLEN; impixtype = IM_PIXTYPE; immax = IM_MAX; immin = IM_MIN; } /* Delete FITS header keyword not needed by IRAF */ hdel (fitsheader,"SIMPLE"); /* Set IRAF image data type */ hgeti4 (fitsheader,"BITPIX", &nbits); switch (nbits) { case 8: pixtype = TY_CHAR; break; case -8: pixtype = TY_UBYTE; break; case 16: pixtype = TY_SHORT; break; case -16: pixtype = TY_USHORT; break; case 32: pixtype = TY_INT; break; case -32: pixtype = TY_REAL; break; case -64: pixtype = TY_DOUBLE; break; default: (void)fprintf(stderr,"Unsupported data type: %d\n", nbits); return (NULL); } irafputi4 (irafheader, impixtype, pixtype); hdel (fitsheader,"BITPIX"); /* Set IRAF image dimensions */ hgeti4 (fitsheader,"NAXIS",&nax); irafputi4 (irafheader, imndim, nax); hdel (fitsheader,"NAXIS"); hgeti4 (fitsheader, "NAXIS1", &n); irafputi4 (irafheader, imlen, n); irafputi4 (irafheader, imphyslen, n); hdel (fitsheader,"NAXIS1"); hgeti4 (fitsheader,"NAXIS2",&n); irafputi4 (irafheader, imlen+4, n); irafputi4 (irafheader, imphyslen+4, n); hdel (fitsheader,"NAXIS2"); if (nax > 2) { hgeti4 (fitsheader,"NAXIS3",&n); irafputi4 (irafheader, imlen+8, n); irafputi4 (irafheader, imphyslen+8, n); hdel (fitsheader,"NAXIS3"); } if (nax > 3) { hgeti4 (fitsheader,"NAXIS4",&n); irafputi4 (irafheader, imlen+12, n); irafputi4 (irafheader, imphyslen+12, n); hdel (fitsheader,"NAXIS4"); } /* Set image pixel value limits */ rmin = 0.0; hgetr4 (fitsheader, "IRAFMIN", &rmin); rmax = 0.0; hgetr4 (fitsheader, "IRAFMAX", &rmax); if (rmin != rmax) { irafputr4 (irafheader, immax, rmax); irafputr4 (irafheader, immin, rmin); } hdel (fitsheader, "IRAFMIN"); hdel (fitsheader, "IRAFMAX"); /* Replace pixel file name, if it is in the FITS header */ if (hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixfile)) { if (strchr (pixfile, '/')) { if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, hdrfile)) { hdrdir = strrchr (hdrfile, '/'); if (hdrdir != NULL) { lhdrdir = hdrdir - hdrfile + 1; if (!strncmp (pixfile, hdrfile, lhdrdir)) { filename = pixfile + lhdrdir; strcpy (temp, "HDR$"); strcat (temp,filename); strcpy (pixfile, temp); } } if (pixfile[0] != '/' && pixfile[0] != 'H') { strcpy (temp, "HDR$"); strcat (temp,pixfile); strcpy (pixfile, temp); } } } if (imhver == 2) irafputc (pixfile, irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else irafputc2 (pixfile, irafheader, IM_PIXFILE, SZ_IMPIXFILE); hdel (fitsheader,"PIXFIL_1"); hdel (fitsheader,"PIXFIL_2"); hdel (fitsheader,"PIXFIL_3"); hdel (fitsheader,"PIXFIL_4"); } /* Replace header file name, if it is in the FITS header */ if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, pixfile)) { if (!strchr (pixfile,'/') && !strchr (pixfile,'$')) { strcpy (temp, "HDR$"); strcat (temp,pixfile); strcpy (pixfile, temp); } if (imhver == 2) irafputc (pixfile, irafheader, IM2_HDRFILE, SZ_IM2HDRFILE); else irafputc2 (pixfile, irafheader, IM_HDRFILE, SZ_IMHDRFILE); hdel (fitsheader, "IMHFIL_1"); hdel (fitsheader, "IMHFIL_2"); hdel (fitsheader, "IMHFIL_3"); hdel (fitsheader, "IMHFIL_4"); } /* Replace image title, if it is in the FITS header */ if (hgets (fitsheader, "OBJECT", SZ_IM2TITLE, title)) { if (imhver == 2) irafputc (title, irafheader, IM2_TITLE, SZ_IM2TITLE); else irafputc2 (title, irafheader, IM_TITLE, SZ_IMTITLE); hdel (fitsheader, "OBJECT"); } hgeti4 (fitsheader, "PIXOFF", &pixoff); hdel (fitsheader, "PIXOFF"); hdel (fitsheader, "PIXOFF"); hdel (fitsheader, "PIXSWAP"); hdel (fitsheader, "PIXSWAP"); hdel (fitsheader, "DATE-MOD"); hdel (fitsheader, "DATE-MOD"); fitsend = ksearch (fitsheader,"END"); /* Find length of FITS header */ fitsend = ksearch (fitsheader,"END"); nlfits = ((fitsend - fitsheader) / 80); /* Find new length of IRAF header */ if (imhver == 2) *nbiraf = LEN_IM2HDR + (81 * nlfits); else *nbiraf = LEN_IMHDR + (162 * nlfits); if (*nbiraf > nbhead) irafheader = realloc (irafheader, *nbiraf); /* Reset modification time */ mtime = lt2tsi (); irafputi4 (irafheader, imtime, mtime); /* Replace user portion of IRAF header with remaining FITS header */ if (imhver == 2) { iraf2u = irafheader + LEN_IM2HDR; iraf2p = iraf2u; for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) { for (i = 0; i < 80; i++) *iraf2p++ = fitsp[i]; *iraf2p++ = 10; } *iraf2p++ = 0; *nbiraf = iraf2p - irafheader; hdrlength = 1 + *nbiraf / 2; } else { irafs = (short *)irafheader; irafu = irafs + (LEN_IMHDR / 2); irafp = irafu; for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) { for (i = 0; i < 80; i++) *irafp++ = (short) fitsp[i]; *irafp++ = 10; } *irafp++ = 0; *irafp++ = 32; *nbiraf = 2 * (irafp - irafs); hdrlength = *nbiraf / 4; } /* Length of header file */ irafputi4 (irafheader, imhlen, hdrlength); /* Offset in .pix file to first pixel data hputi4 (fitsheader, "PIXOFF", pixoff); */ /* Return number of bytes in new IRAF header */ return (irafheader); } int irafgeti4 (irafheader, offset) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ { char *ctemp, *cheader; int temp; cheader = irafheader; ctemp = (char *) &temp; /* If header swap flag not set, set it now */ if (headswap < 0) { if (cheader[offset] > 0) headswap = 1; else headswap = 0; } if (machswap() != headswap) { ctemp[3] = cheader[offset]; ctemp[2] = cheader[offset+1]; ctemp[1] = cheader[offset+2]; ctemp[0] = cheader[offset+3]; } else { ctemp[0] = cheader[offset]; ctemp[1] = cheader[offset+1]; ctemp[2] = cheader[offset+2]; ctemp[3] = cheader[offset+3]; } return (temp); } float irafgetr4 (irafheader, offset) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ { char *ctemp, *cheader; float temp; cheader = irafheader; ctemp = (char *) &temp; /* If header swap flag not set, set it now */ if (headswap < 0) { if (cheader[offset] > 0) headswap = 1; else headswap = 0; } if (machswap() != headswap) { ctemp[3] = cheader[offset]; ctemp[2] = cheader[offset+1]; ctemp[1] = cheader[offset+2]; ctemp[0] = cheader[offset+3]; } else { ctemp[0] = cheader[offset]; ctemp[1] = cheader[offset+1]; ctemp[2] = cheader[offset+2]; ctemp[3] = cheader[offset+3]; } return (temp); } /* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */ char * irafgetc2 (irafheader, offset, nc) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *irafstring, *string; irafstring = irafgetc (irafheader, offset, 2*(nc+1)); string = iraf2str (irafstring, nc); free (irafstring); return (string); } /* IRAFGETC -- Get character string from arbitrary part of IRAF header */ char * irafgetc (irafheader, offset, nc) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *ctemp, *cheader; int i; cheader = irafheader; ctemp = (char *) calloc (nc+1, 1); if (ctemp == NULL) { (void)fprintf(stderr, "IRAFGETC Cannot allocate %d-byte variable\n", nc+1); return (NULL); } for (i = 0; i < nc; i++) { ctemp[i] = cheader[offset+i]; if (ctemp[i] > 0 && ctemp[i] < 32) ctemp[i] = ' '; } return (ctemp); } /* Convert IRAF 2-byte/char string to 1-byte/char string */ char * iraf2str (irafstring, nchar) char *irafstring; /* IRAF 2-byte/character string */ int nchar; /* Number of characters in string */ { char *string; int i, j; /* Set swap flag according to position of nulls in 2-byte characters */ if (headswap < 0) { if (irafstring[0] != 0 && irafstring[1] == 0) headswap = 1; else if (irafstring[0] == 0 && irafstring[1] != 0) headswap = 0; else return (NULL); } string = (char *) calloc (nchar+1, 1); if (string == NULL) { (void)fprintf(stderr, "IRAF2STR Cannot allocate %d-byte variable\n", nchar+1); return (NULL); } /* Swap bytes, if requested */ if (headswap) j = 0; else j = 1; /* Convert appropriate byte of input to output character */ for (i = 0; i < nchar; i++) { string[i] = irafstring[j]; j = j + 2; } return (string); } /* IRAFPUTI4 -- Insert 4-byte integer into arbitrary part of IRAF header */ static void irafputi4 (irafheader, offset, inum) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ int inum; /* Number to put into header */ { char *cn, *chead; chead = irafheader; cn = (char *) &inum; if (headswap < 0) headswap = 0; if (headswap != machswap()) { chead[offset+3] = cn[0]; chead[offset+2] = cn[1]; chead[offset+1] = cn[2]; chead[offset] = cn[3]; } else { chead[offset] = cn[0]; chead[offset+1] = cn[1]; chead[offset+2] = cn[2]; chead[offset+3] = cn[3]; } return; } /* IRAFPUTR4 -- Insert 4-byte real number into arbitrary part of IRAF header */ static void irafputr4 (irafheader, offset, rnum) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ float rnum; /* Number to put into header */ { char *cn, *chead; chead = irafheader; cn = (char *) &rnum; if (headswap < 0) headswap = 0; if (headswap != machswap()) { chead[offset+3] = cn[0]; chead[offset+2] = cn[1]; chead[offset+1] = cn[2]; chead[offset] = cn[3]; } else { chead[offset] = cn[0]; chead[offset+1] = cn[1]; chead[offset+2] = cn[2]; chead[offset+3] = cn[3]; } return; } /* IRAFPUTC2 -- Insert character string into arbitrary part of v.1 IRAF header */ static void irafputc2 (string, irafheader, offset, nc) char *string; /* String to insert into header */ char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *irafstring; irafstring = (char *) calloc (2 * nc, 1); if (irafstring == NULL) { (void)fprintf(stderr, "IRAFPUTC2 Cannot allocate %d-byte variable\n", 2 * nc); } str2iraf (string, irafstring, nc); irafputc (irafstring, irafheader, offset, 2*nc); return; } /* IRAFPUTC -- Insert character string into arbitrary part of IRAF header */ static void irafputc (string, irafheader, offset, nc) char *string; /* String to insert into header */ char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *chead; int i; chead = irafheader; for (i = 0; i < nc; i++) chead[offset+i] = string[i]; return; } /* STR2IRAF -- Convert 1-byte/char string to IRAF 2-byte/char string */ static void str2iraf (string, irafstring, nchar) char *string; /* 1-byte/character string */ char *irafstring; /* IRAF 2-byte/character string */ int nchar; /* Maximum number of characters in IRAF string */ { int i, j, nc, nbytes; nc = strlen (string); /* Fill output string with zeroes */ nbytes = nchar * 2; for (i = 0; i < nbytes; i++) irafstring[i] = 0; /* If swapped, start with first byte of 2-byte characters */ if (headswap) j = 0; else j = 1; /* Move input characters to appropriate bytes of output */ for (i = 0; i < nchar; i++) { if (i > nc) irafstring[j] = 0; else irafstring[j] = string[i]; j = j + 2; } return; } /* IRAFSWAP -- Reverse bytes of any type of vector in place */ static void irafswap (bitpix, string, nbytes) int bitpix; /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ char *string; /* Address of starting point of bytes to swap */ int nbytes; /* Number of bytes to swap */ { switch (bitpix) { case 16: if (nbytes < 2) return; irafswap2 (string,nbytes); break; case 32: if (nbytes < 4) return; irafswap4 (string,nbytes); break; case -16: if (nbytes < 2) return; irafswap2 (string,nbytes); break; case -32: if (nbytes < 4) return; irafswap4 (string,nbytes); break; case -64: if (nbytes < 8) return; irafswap8 (string,nbytes); break; } return; } /* IRAFSWAP2 -- Swap bytes in string in place */ static void irafswap2 (string,nbytes) char *string; /* Address of starting point of bytes to swap */ int nbytes; /* Number of bytes to swap */ { char *sbyte, temp, *slast; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp = sbyte[0]; sbyte[0] = sbyte[1]; sbyte[1] = temp; sbyte= sbyte + 2; } return; } /* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */ static void irafswap4 (string,nbytes) char *string; /* Address of Integer*4 or Real*4 vector */ int nbytes; /* Number of bytes to reverse */ { char *sbyte, *slast; char temp0, temp1, temp2, temp3; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp3 = sbyte[0]; temp2 = sbyte[1]; temp1 = sbyte[2]; temp0 = sbyte[3]; sbyte[0] = temp0; sbyte[1] = temp1; sbyte[2] = temp2; sbyte[3] = temp3; sbyte = sbyte + 4; } return; } /* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */ static void irafswap8 (string,nbytes) char *string; /* Address of Real*8 vector */ int nbytes; /* Number of bytes to reverse */ { char *sbyte, *slast; char temp[8]; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp[7] = sbyte[0]; temp[6] = sbyte[1]; temp[5] = sbyte[2]; temp[4] = sbyte[3]; temp[3] = sbyte[4]; temp[2] = sbyte[5]; temp[1] = sbyte[6]; temp[0] = sbyte[7]; sbyte[0] = temp[0]; sbyte[1] = temp[1]; sbyte[2] = temp[2]; sbyte[3] = temp[3]; sbyte[4] = temp[4]; sbyte[5] = temp[5]; sbyte[6] = temp[6]; sbyte[7] = temp[7]; sbyte = sbyte + 8; } return; } /* Set flag if machine on which program is executing is not FITS byte order * ( i.e., if it is an Alpha or PC instead of a Sun ) */ static int machswap () { char *ctest; int itest; itest = 1; ctest = (char *)&itest; if (*ctest) return (1); else return (0); } /* ISIRAF -- return 1 if IRAF imh file, else 0 */ int isiraf (filename) char *filename; /* Name of file for which to find size */ { if (strchr (filename, '=')) return (0); else if (strsrch (filename, ".imh")) return (1); else return (0); } /* IRAFSIZE -- return size of file in bytes */ static int irafsize (diskfile) FILE *diskfile; /* Descriptor of file for which to find size */ { long filesize; long offset; offset = (long) 0; /* Move to end of the file */ if (fseek (diskfile, offset, SEEK_END) == 0) { /* Position is the size of the file */ filesize = ftell (diskfile); /* Move file pointer back tot he start of the file */ fseek (diskfile, offset, SEEK_SET); } else filesize = -1; return (filesize); } /* Feb 15 1996 New file * Apr 10 1996 Add more documentation * Apr 17 1996 Print error message on open failure * Jun 5 1996 Add byte swapping (reversal); use streams * Jun 10 1996 Make fixes after running lint * Jun 12 1996 Use IMSWAP subroutines instead of local ones * Jul 3 1996 Go back to using local IRAFSWAP subroutines * Jul 3 1996 Write to pixel file from FITS header * Jul 10 1996 Allocate all headers * Aug 13 1996 Add unistd.h to include list * Aug 26 1996 Allow 1-d images; fix comments; fix arguments after lint * Aug 26 1996 Add IRAF header lingth argument to IRAFWIMAGE and IRAFWHEAD * Aug 28 1996 Clean up code in IRAF2FITS * Aug 30 1996 Use write instead of fwrite * Sep 4 1996 Fix write mode bug * Oct 15 1996 Drop unused variables * Oct 17 1996 Minor fix after lint; cast arguments to STR2IRAF * * May 15 1997 Fix returned header length in IRAF2FITS * Dec 19 1997 Add IRAF version 2 .imh files * * Jan 2 1998 Allow uneven length of user parameter lines in IRAF headers * Jan 6 1998 Fix output of imh2 headers; allow newlines in imh1 headers * Jan 14 1998 Handle byte reversing correctly * Apr 17 1998 Add new IRAF data types unsigned char and unsigned short * Apr 30 1998 Fix error return if illegal data type after Allan Brighton * May 15 1998 Delete header keywords used for IRAF binary values * May 15 1998 Fix bug so FITS OBJECT is put into IRAF title * May 26 1998 Fix bug in fits2iraf keeping track of end of header * May 27 1998 Include fitsio.h instead of fitshead.h * Jun 4 1998 Write comments into header for converted IRAF binary values * Jun 4 1998 Pad FITS strings to 8 character minimum * Jul 24 1998 Write header file length to IRAF header file * Jul 27 1998 Print error messages to stderr for all failed malloc's * Jul 27 1998 Fix bug padding FITS header with spaces in iraf2fits * Jul 27 1998 Write modification time to IRAF header file * Aug 6 1998 Change fitsio.h to fitsfile.h; imhio.c to imhfile.c * Oct 1 1998 Set irafswap flag only once per file * Oct 5 1998 Add subroutines irafsize() and isiraf() * Nov 16 1998 Fix byte-swap checking * * Jan 27 1999 Read and write all of 3D image if one dimension is =1 * Jul 13 1999 Improve error messages; change irafsize() argument to fd * Sep 22 1999 Don't copy OBJECT keyword from .imh file; use binary title * Oct 14 1999 Set FITS header length * Oct 20 1999 Allocate 5000 extra bytes for IRAF header * Nov 2 1999 Fix getclocktime() to use only time.h subroutines * Nov 2 1999 Add modification date and time to FITS header in iraf2fits() * Nov 24 1999 Delete HEADSWAP, IMHVER, DATE-MOD from header before writing * Nov 29 1999 Delete PIXSWAP, IRAF-MIN, IRAF-MAX from header before writing * * Jan 13 2000 Fix bug which dropped characters in iraf2fits() * Feb 3 2000 Declare timezone long, not time_t; drop unused variable * Mar 7 2000 Add more code to keep pixel file path short * Mar 10 2000 Fix bugs when writing .imh file headers * Mar 21 2000 Change computation of IRAF time tags to use only data structure * Mar 22 2000 Move IRAF time tag computation to lt2tsi() in dateutil.c * Mar 24 2000 Use Unix file update time if none in header * Mar 27 2000 Use hputm() to save file paths up to 256 characters * Mar 27 2000 Write filename comments after 1st keyword with short value * Mar 27 2000 Allocate pixel file name in same_path to imh2 length * Mar 29 2000 Add space after last linefeed of header in fits2iraf() * Apr 28 2000 Dimension pixname in irafwimage() * May 1 2000 Fix code for updating pixel file name with HDR$ in fits2iraf() * Jun 2 2000 Drop unused variables in fits2iraf() after lint * Jun 12 2000 If pixel filename has no / or $, use same path as header file * Sep 6 2000 Use header directory if pixel file not found at its pathname * * Jan 11 2001 Print all messages to stderr * Aug 24 2001 In isiraf(), return 0 if argument contains an equal sign * * Apr 8 2002 Fix bug in error message for unidentified nbits in fits2iraf() * * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Oct 31 2003 Read image only in irafrimage() if physical dimension > image dim. * Nov 3 2003 Set NAXISi to image, not physical dimensions in iraf2fits() * * Jun 13 2005 Drop trailing spaces on pixel file name * * Jun 20 2006 Initialize uninitialized variables * * Jan 4 2007 Change hputr4() calls to send pointer to value * Jan 8 2007 Drop unused variable nbx in irafrimage() * Jan 8 2007 Align header and image buffers properly by 4 and by BITPIX * * May 20 2011 Free newpixname, not pixname in irafwimage() * * Mar 27 2012 Fix pixname's appending to newpixname to avoid overflow */