Index: trunk/psLib/src/fits/psFits.c
===================================================================
--- trunk/psLib/src/fits/psFits.c	(revision 2806)
+++ trunk/psLib/src/fits/psFits.c	(revision 2962)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-12-23 19:13:53 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-01-12 22:17:01 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -196,6 +196,5 @@
 }
 
-psFits* psFitsAlloc(const char* name,                  ///< the FITS file name
-                    bool readwrite)                    ///< if TRUE, the file is open for read/write.
+psFits* psFitsAlloc(const char* name)
 {
     int status = 0;
@@ -207,10 +206,12 @@
         return NULL;
     }
-
-    int iomode = (readwrite) ? READWRITE : READONLY;
 
     /* Open/Create the FITS file */
     if (access(name, F_OK) == 0) {     // file exists
-        (void)fits_open_file(&fptr, name, iomode, &status);
+        (void)fits_open_file(&fptr, name, READWRITE, &status);
+        if (fptr == NULL) { // if failed, try openning as just read-only
+            status = 0;
+            (void)fits_open_file(&fptr, name, READONLY, &status);
+        }
         if (fptr == NULL || status != 0) {
             char fitsErr[MAX_STRING_LENGTH];
@@ -221,5 +222,5 @@
             return NULL;
         }
-    } else {  // file does not exist
+    } else {  // file does not exist, so create.
         (void)fits_create_file(&fptr, name, &status);
         if (fptr == NULL || status != 0) {
@@ -253,4 +254,10 @@
     }
 
+    if (extname == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_EXTNAME_NULL);
+        return false;
+    }
+
 
     if (fits_movnam_hdu(fits->p_fd, ANY_HDU, (char*)extname, 0, &status) != 0) {
@@ -317,5 +324,5 @@
     }
 
-    return hdutype-1;
+    return hdutype;
 }
 
@@ -339,4 +346,32 @@
     }
     return psStringCopy(name);
+}
+
+bool psFitsSetExtName(psFits* fits, const char* name)
+{
+    if (fits == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        return false;
+    }
+
+    if (name == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_EXTNAME_NULL);
+        return false;
+    }
+
+    int status = 0;
+
+    if (fits_update_key_str(fits->p_fd, "EXTNAME", (char*)name, NULL, &status) != 0) {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_WRITE_FAILED,
+                fits->filename, fitsErr);
+        return false;
+    }
+
+    return true;
 }
 
@@ -540,4 +575,181 @@
 }
 
+psImage* psFitsReadImage(psImage* output, // a psImage to recycle.
+                         psFits* fits,    // the psFits object
+                         psRegion region, // the region in the FITS image to read
+                         int z)           // the z-plane in the FITS image cube to read
+{
+    psS32 status = 0;           /* CFITSIO file vars */
+    psS32 nAxis = 0;
+    psS32 anynull = 0;
+    psS32 bitPix = 0;           /* Pixel type */
+    long nAxes[3];
+    long firstPixel[3];         /* lower-left corner of image subset */
+    long lastPixel[3];          /* upper-right corner of image subset */
+    long increment[3];          /* increment for image subset */
+    char fitsErr[80] = "";      /* CFITSIO error message string */
+    psS32 fitsDatatype = 0;
+    psS32 datatype = 0;
+
+    if (fits == NULL)
+    {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                PS_ERRORTEXT_psFits_NULL);
+        psFree(output);
+        return NULL;
+    }
+
+    // check to see if we even are positioned on an image HDU
+    int hdutype;
+    if ( fits_get_hdu_type(fits->p_fd,&hdutype, &status) != 0)
+    {
+        char fitsErr[MAX_STRING_LENGTH];
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED,
+                fitsErr);
+        return NULL;
+    }
+    if (hdutype != IMAGE_HDU)
+    {
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE);
+        return NULL;
+    }
+
+    /* Get the data type 'bitPix' from the FITS image */
+    if (fits_get_img_equivtype(fits->p_fd, &bitPix, &status) != 0)
+    {
+        fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_DATATYPE_UNKNOWN,
+                fitsErr);
+        psFree(output);
+        return NULL;
+    }
+
+    /* Get the dimensions 'nAxis' from the FITS image */
+    if (fits_get_img_dim(fits->p_fd, &nAxis, &status) != 0)
+    {
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_IMAGE_DIM_UNKNOWN,
+                fitsErr);
+        psFree(output);
+        return NULL;
+    }
+
+    /* Validate the number of axis */
+    if ((nAxis < 2) || (nAxis > 3))
+    {
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_IMAGE_DIMENSION_UNSUPPORTED,
+                nAxis);
+        psFree(output);
+        return NULL;
+    }
+
+    /* Get the Image size from the FITS file */
+    if (fits_get_img_size(fits->p_fd, nAxis, nAxes, &status) != 0)
+    {
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_IMAGE_SIZE_UNKNOWN,
+                fitsErr);
+        psFree(output);
+        return NULL;
+    }
+
+    firstPixel[0] = region.x0 + 1;
+    firstPixel[1] = region.y0 + 1;
+    firstPixel[2] = z + 1;
+
+    if (region.x1 > 0)
+    {
+        lastPixel[0] = region.x1;
+    } else
+    {
+        lastPixel[0] = nAxes[0] + region.x1; // n.b., region.x1 < 0
+    }
+    if (region.y1 > 0)
+    {
+        lastPixel[1] = region.y1;
+    } else
+    {
+        lastPixel[1] = nAxes[1] + region.y1; // n.b., region.y1 < 0
+    }
+    lastPixel[2] = z + 1;
+
+    increment[0] = 1;
+    increment[1] = 1;
+    increment[2] = 1;
+
+    switch (bitPix)
+    {
+    case BYTE_IMG:
+        datatype = PS_TYPE_U8;
+        fitsDatatype = TBYTE;
+        break;
+    case SBYTE_IMG:
+        datatype = PS_TYPE_S8;
+        fitsDatatype = TSBYTE;
+        break;
+    case USHORT_IMG:
+        datatype = PS_TYPE_U16;
+        fitsDatatype = TUSHORT;
+        break;
+    case SHORT_IMG:
+        datatype = PS_TYPE_S16;
+        fitsDatatype = TSHORT;
+        break;
+    case ULONG_IMG:
+        datatype = PS_TYPE_U32;
+        fitsDatatype = TUINT;
+        break;
+    case LONG_IMG:
+        datatype = PS_TYPE_S32;
+        fitsDatatype = TINT;
+        break;
+    case LONGLONG_IMG:
+        datatype = PS_TYPE_S64;
+        fitsDatatype = TLONGLONG;
+        break;
+    case FLOAT_IMG:
+        datatype = PS_TYPE_F32;
+        fitsDatatype = TFLOAT;
+        break;
+    case DOUBLE_IMG:
+        datatype = PS_TYPE_F64;
+        fitsDatatype = TDOUBLE;
+        break;
+    default:
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_FITS_TYPE_UNSUPPORTED,
+                bitPix);
+        psFree(output);
+        return NULL;
+    }
+
+    output = psImageRecycle(output,
+                            lastPixel[0]-firstPixel[0]+1,
+                            lastPixel[1]-firstPixel[1]+1,
+                            datatype);
+
+    // n.b., this assumes contiguous image buffer
+    if (fits_read_subset(fits->p_fd, fitsDatatype, firstPixel, lastPixel, increment,
+                         NULL, output->data.V[0], &anynull, &status) != 0)
+    {
+        psFree(output);
+        (void)fits_get_errstatus(status, fitsErr);
+        psError(PS_ERR_IO, true,
+                PS_ERRORTEXT_psFits_READ_FAILED,
+                fitsErr);
+        return NULL;
+    }
+
+    return output;
+
+}
+
 bool psFitsWriteImage(psFits* fits,
                       const psMetadata* header,
@@ -594,14 +806,13 @@
     }
 
-    long firstPixel = (numZPlanes-1)*numRows*numCols; // start write in last z-plane
-
     if (input->parent == NULL) { // if no parent, assume that the image data is contiguous
         fits_write_img(fits->p_fd,
                        dataType,              // datatype
-                       firstPixel,                     // writing to the first z-plane
+                       1,                     // writing to the first z-plane
                        numCols*numRows,       // number of elements to write, i.e., the whole image
                        input->data.V[0],      // the data
                        &status);
     } else { // image data may not be contiguous; write one row at a time
+        int firstPixel = 1;
         for (int row = 0; row < numRows; row++) {
             fits_write_img(fits->p_fd,
