summaryrefslogtreecommitdiffstats
path: root/funtools/wcs/imhfile.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-25 20:57:49 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-25 20:57:49 (GMT)
commitd1c4bf158203c4e8ec29fdeb83fd311e36320885 (patch)
tree15874534e282f67505ce4af5ba805a1ff70ec43e /funtools/wcs/imhfile.c
parente19a18e035dc4d0e8e215f9b452bb9ef6f58b9d7 (diff)
parent339420dd5dd874c41f6bab5808291fb4036dd022 (diff)
downloadblt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.zip
blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.tar.gz
blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.tar.bz2
Merge commit '339420dd5dd874c41f6bab5808291fb4036dd022' as 'funtools'
Diffstat (limited to 'funtools/wcs/imhfile.c')
-rw-r--r--funtools/wcs/imhfile.c1941
1 files changed, 1941 insertions, 0 deletions
diff --git a/funtools/wcs/imhfile.c b/funtools/wcs/imhfile.c
new file mode 100644
index 0000000..b618686
--- /dev/null
+++ b/funtools/wcs/imhfile.c
@@ -0,0 +1,1941 @@
+/*** 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 <stdio.h> /* define stderr, FD, and NULL */
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#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
+ */