Index: trunk/psModules/src/camera/pmFPAfile.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfile.c	(revision 16069)
+++ trunk/psModules/src/camera/pmFPAfile.c	(revision 16186)
@@ -74,6 +74,5 @@
   file->fits = NULL;
   file->compression = NULL;
-  file->bitpix = 0;
-  file->floatType = PS_FITS_FLOAT_NONE;
+  file->options = NULL;
   file->names = psMetadataAlloc();
 
@@ -192,5 +191,5 @@
       char *name = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
       if (name != NULL) {
-	psStringSubstitute(&newName, name, "{CHIP.NAME}");
+        psStringSubstitute(&newName, name, "{CHIP.NAME}");
       }
     }
@@ -201,5 +200,5 @@
       char *name = psMetadataLookupStr (NULL, chip->concepts, "CHIP.ID");
       if (name != NULL) {
-	psStringSubstitute(&newName, name, "{CHIP.ID}");
+        psStringSubstitute(&newName, name, "{CHIP.ID}");
       }
     }
@@ -220,5 +219,5 @@
       char *name = psMetadataLookupStr (NULL, cell->concepts, "CELL.NAME");
       if (name != NULL) {
-	psStringSubstitute(&newName, name, "{CELL.NAME}");
+        psStringSubstitute(&newName, name, "{CELL.NAME}");
       }
     }
@@ -243,5 +242,5 @@
       char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.FILTER");
       if (name && *name) {
-	psStringSubstitute(&newName, name, "{FILTER}");
+        psStringSubstitute(&newName, name, "{FILTER}");
       }
     }
@@ -251,5 +250,5 @@
       char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.FILTERID");
       if (name && *name) {
-	psStringSubstitute(&newName, name, "{FILTER.ID}");
+        psStringSubstitute(&newName, name, "{FILTER.ID}");
       }
     }
@@ -259,5 +258,5 @@
       char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.INSTRUMENT");
       if (name && *name) {
-	psStringSubstitute(&newName, name, "{CAMERA}");
+        psStringSubstitute(&newName, name, "{CAMERA}");
       }
     }
@@ -267,5 +266,5 @@
       char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.INSTRUMENT");
       if (name && *name) {
-	psStringSubstitute(&newName, name, "{INSTRUMENT}");
+        psStringSubstitute(&newName, name, "{INSTRUMENT}");
       }
     }
@@ -275,5 +274,5 @@
       char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.DETECTOR");
       if (name && *name) {
-	psStringSubstitute(&newName, name, "{DETECTOR}");
+        psStringSubstitute(&newName, name, "{DETECTOR}");
       }
     }
@@ -283,5 +282,5 @@
       char *name = psMetadataLookupStr (NULL, fpa->concepts, "FPA.TELESCOPE");
       if (name && *name) {
-	psStringSubstitute(&newName, name, "{TELESCOPE}");
+        psStringSubstitute(&newName, name, "{TELESCOPE}");
       }
     }
@@ -340,5 +339,5 @@
   if (view->cell >= inChip->cells->n) {
     psError(PS_ERR_IO, true, "Requested cell == %d>= inChip->cells->n == %ld",
-	    view->cell, inChip->cells->n);
+            view->cell, inChip->cells->n);
     return false;
   }
@@ -387,5 +386,5 @@
   if (view->cell >= inChip->cells->n) {
     psError(PS_ERR_IO, true, "Requested cell == %d>= inChip->cells->n == %ld",
-	    view->cell, inChip->cells->n);
+            view->cell, inChip->cells->n);
     return false;
   }
Index: trunk/psModules/src/camera/pmFPAfile.h
===================================================================
--- trunk/psModules/src/camera/pmFPAfile.h	(revision 16069)
+++ trunk/psModules/src/camera/pmFPAfile.h	(revision 16186)
@@ -4,6 +4,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-12-27 02:07:16 $
+ * @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-01-23 03:10:51 $
  * Copyright 2004-2005 Institute for Astronomy, University of Hawaii
  */
@@ -65,6 +65,5 @@
     psFits *fits;                       // for I/O files of fits type (IMAGE, CMP, CMF) we carry a file handle
     psFitsCompression *compression;     // Compression for FITS images
-    int bitpix;                         // Bits per pixel for output
-    psFitsFloat floatType;              // Custom floating-point
+    psFitsOptions *options;             // FITS I/O options
 
     bool wrote_phu;                     // have we written a PHU for this file?
Index: trunk/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 16069)
+++ trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 16186)
@@ -35,4 +35,34 @@
     }
     int value = psMetadataItemParseS32(item); // Value of interst
+    return value;
+}
+
+// Parse an option from a metadata, returning the appropriate float value
+static float parseOptionFloat(const psMetadata *md, // Metadata containing the option
+                              const char *name, // Option name
+                              const char *source // Description of source, for warning messages
+                              )
+{
+    psMetadataItem *item = psMetadataLookup(md, name); // Item with the value of interest
+    if (!item) {
+        psWarning("Unable to find value for %s in %s", name, source);
+        return NAN;
+    }
+    int value = psMetadataItemParseF32(item); // Value of interst
+    return value;
+}
+
+// Parse an option from a metadata, returning the appropriate double value
+static double parseOptionDouble(const psMetadata *md, // Metadata containing the option
+                                const char *name, // Option name
+                                const char *source // Description of source, for warning messages
+                                )
+{
+    psMetadataItem *item = psMetadataLookup(md, name); // Item with the value of interest
+    if (!item) {
+        psWarning("Unable to find value for %s in %s", name, source);
+        return NAN;
+    }
+    int value = psMetadataItemParseF64(item); // Value of interst
     return value;
 }
@@ -212,46 +242,91 @@
         psMetadata *fitsTypes = psMetadataLookupMetadata(&status, camera, "FITS"); // The FITS schemes
         if (!fitsTypes) {
-            psWarning("Unable to find FITS in camera configuration --- compression disabled.");
-            goto COMPRESSION_DONE;
+            psWarning("Unable to find FITS in camera configuration.");
+            goto FITS_OPTIONS_DONE;
         }
         psMetadata *scheme = psMetadataLookupMetadata(NULL, fitsTypes, fitsType); // FITS scheme
         if (!scheme) {
-            psWarning("Unable to find %s in FITS in camera configuration --- compression disabled.",
-                      fitsType);
-            goto COMPRESSION_DONE;
-        }
-        const char *typeString = psMetadataLookupStr(NULL, scheme, "COMP"); // Compression type
-        if (!typeString || strlen(typeString) == 0) {
-            psWarning("Can't find COMP in FITS scheme %s --- compression disabled.", fitsType);
-            goto COMPRESSION_DONE;
-        }
-        psFitsCompressionType type = psFitsCompressionTypeFromString(typeString); // Compression type enum
-
-        psString source = NULL;         // Source of options
+            psWarning("Unable to find %s in FITS in camera configuration --- will use defaults.", fitsType);
+            goto FITS_OPTIONS_DONE;
+        }
+
+        psString source = NULL;     // Source of options
         psStringAppend(&source, "%s in FITS in camera %s", fitsType, cameraName);
-        file->bitpix = parseOptionInt(scheme, "BITPIX", source, 0); // Bits per pixel
+
+        psFitsOptions *options = file->options = psFitsOptionsAlloc(); // FITS I/O options
 
         // Custom floating-point
-        const char *floatName = psMetadataLookupStr(NULL, scheme, "FLOAT"); // Name of custom floating-point
+        const char *floatName = psMetadataLookupStr(NULL, scheme, "FLOAT"); // Name of custom float
         if (floatName) {
             psString fullName = NULL;   // Full name of custom floating-point
             psStringAppend(&fullName, "FLOAT_%s", floatName);
-            file->floatType = psFitsFloatTypeFromString(fullName);
+            options->floatType = psFitsFloatTypeFromString(fullName);
             psFree(fullName);
         }
 
-        psVector *tile = psVectorAlloc(3, PS_TYPE_S32); // Tile sizes
-        tile->data.S32[0] = parseOptionInt(scheme, "TILE.X", source, 0); // Tiling in x
-        tile->data.S32[1] = parseOptionInt(scheme, "TILE.Y", source, 1); // Tiling in y
-        tile->data.S32[2] = parseOptionInt(scheme, "TILE.Z", source, 1); // Tiling in z
-        int noise = parseOptionInt(scheme, "NOISE", source, 16); // Noise bits
-        int hscale = parseOptionInt(scheme, "HSCALE", source, 0); // Scaling for HCOMPRESS
-        int hsmooth = parseOptionInt(scheme, "HSMOOTH", source, 0); // Smoothing for HCOMPRESS
+        options->bitpix = parseOptionInt(scheme, "BITPIX", source, 0); // Bits per pixel
+
+        // Scaling options
+        bool mdok;                  // Status of MD lookup
+        const char *scalingString = psMetadataLookupStr(&mdok, scheme, "SCALING"); // Scaling name
+        if (scalingString) {
+            options->scaling = psFitsScalingFromString(scalingString); // Scaling method
+
+            switch (options->scaling) {
+              case PS_FITS_SCALE_NONE:
+              case PS_FITS_SCALE_RANGE:
+                // No options required
+                break;
+              case PS_FITS_SCALE_STDEV_POSITIVE:
+              case PS_FITS_SCALE_STDEV_NEGATIVE:
+                options->stdevNum = parseOptionFloat(scheme, "STDEV.NUM", source); // Padding to edge
+                if (!isfinite(options->stdevNum)) {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Bad value for STDEV.NUM for %s", source);
+                    psFree(source);
+                    psFree(file);
+                    return NULL;
+                }
+                // Flow through
+              case PS_FITS_SCALE_STDEV_BOTH:
+                options->stdevBits = parseOptionInt(scheme, "STDEV.BITS", source, 0); // Bits for stdev
+                if (options->stdevBits <= 0) {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Bad value for STDEV.BITS (%d) for %s",
+                            options->stdevBits, source);
+                    psFree(source);
+                    psFree(file);
+                    return NULL;
+                }
+                break;
+              case PS_FITS_SCALE_MANUAL:
+                options->bscale = parseOptionDouble(scheme, "BSCALE", source); // Scaling
+                options->bzero = parseOptionDouble(scheme, "BZERO", source); // Zero point
+                break;
+              default:
+                psAbort("Should never get here.");
+            }
+        }
+
+        // Compression options
+        const char *compressString = psMetadataLookupStr(NULL, scheme, "COMPRESSION"); // Compression type
+        if (compressString) {
+            psFitsCompressionType type = psFitsCompressionTypeFromString(compressString); // Compression
+            psVector *tile = psVectorAlloc(3, PS_TYPE_S32); // Tile sizes
+            tile->data.S32[0] = parseOptionInt(scheme, "TILE.X", source, 0); // Tiling in x
+            tile->data.S32[1] = parseOptionInt(scheme, "TILE.Y", source, 1); // Tiling in y
+            tile->data.S32[2] = parseOptionInt(scheme, "TILE.Z", source, 1); // Tiling in z
+            int noise = parseOptionInt(scheme, "NOISE", source, 16); // Noise bits
+            int hscale = 0, hsmooth = 0;// Scaling and smoothing for HCOMPRESS
+            if (type == PS_FITS_COMPRESS_HCOMPRESS) {
+                hscale = parseOptionInt(scheme, "HSCALE", source, 0);
+                hsmooth = parseOptionInt(scheme, "HSMOOTH", source, 0);
+            }
+
+            file->compression = psFitsCompressionAlloc(type, tile, noise, hscale, hsmooth);
+            psFree(tile);
+        }
+
         psFree(source);
-
-        file->compression = psFitsCompressionAlloc(type, tile, noise, hscale, hsmooth);
-        psFree(tile);
-    }
-COMPRESSION_DONE:
+    }
+ FITS_OPTIONS_DONE:
 
     file->fileLevel = pmFPAPHULevel(format);
@@ -971,6 +1046,6 @@
         }
         file->detrend = results;
-	file->fileLevel = pmFPALevelFromName(results->level);
-	if (file->fileLevel == PM_FPA_LEVEL_NONE) {
+        file->fileLevel = pmFPALevelFromName(results->level);
+        if (file->fileLevel == PM_FPA_LEVEL_NONE) {
             psError (PS_ERR_IO, false, "invalid file level for selected detrend data");
             return NULL;
@@ -1021,5 +1096,5 @@
     // inherit the concepts from the src fpa:
     pmFPACopyConcepts(file->fpa, file->src);
-    
+
     return file;
 }
@@ -1233,8 +1308,8 @@
 // pmFPAfile is being used internally.
 pmReadout *pmFPAGenerateReadout(const pmConfig *config, // configuration information
-				const pmFPAview *view, // select background for this entry
-				const char *name, // name of internal/external file
-				const pmFPA *fpa, // use this fpa to generate
-				const psImageBinning *binning) {
+                                const pmFPAview *view, // select background for this entry
+                                const char *name, // name of internal/external file
+                                const pmFPA *fpa, // use this fpa to generate
+                                const psImageBinning *binning) {
   pmReadout *readout = NULL;
 
@@ -1246,5 +1321,5 @@
     readout = pmFPAfileDefineInternal (config->files, name, binning->nXruff, binning->nYruff, PS_TYPE_F32);
     return readout;
-  } 
+  }
 
   // if the mode is INTERNAL, it has been defined in a previous call.  XXX This seems to require
@@ -1253,5 +1328,5 @@
     readout = file->readout;
     return readout;
-  } 
+  }
 
   // we are using this pmFPAfile as an I/O file: select readout or create
Index: trunk/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileIO.c	(revision 16069)
+++ trunk/psModules/src/camera/pmFPAfileIO.c	(revision 16186)
@@ -685,17 +685,17 @@
         psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "CLASSID"); // Menu of class IDs
         if (!status || !menu) {
-	    psError(PS_ERR_IO, false, "Unable to find CLASSID metadata in camera configuration");
-	    return false;
-        } 
-	const char *rule = psMetadataLookupStr(&status, menu, file->detrend->level); // Rule for class_id
-	if (!status || !rule || strlen(rule) == 0) {
-	    psError(PS_ERR_IO, false, "Unable to find %s in CLASSID in camera configuration", file->detrend->level);
-	    return false;
-	} 
-	classId = pmFPAfileNameFromRule(rule, file, view);
-	if (!classId) {
-	    psError(PS_ERR_IO, false, "error converting CLASSID rule to name: %s\n", rule);
-	    return false;
-	}
+            psError(PS_ERR_IO, false, "Unable to find CLASSID metadata in camera configuration");
+            return false;
+        }
+        const char *rule = psMetadataLookupStr(&status, menu, file->detrend->level); // Rule for class_id
+        if (!status || !rule || strlen(rule) == 0) {
+            psError(PS_ERR_IO, false, "Unable to find %s in CLASSID in camera configuration", file->detrend->level);
+            return false;
+        }
+        classId = pmFPAfileNameFromRule(rule, file, view);
+        if (!classId) {
+            psError(PS_ERR_IO, false, "error converting CLASSID rule to name: %s\n", rule);
+            return false;
+        }
         psTrace ("psModules.camera", 6, "looking for detrend (%s, %s)\n", file->detrend->detID, classId);
         psFree (file->filename);
@@ -751,5 +751,5 @@
         }
 
-	// XXX these are probably only needed for WRITE files
+        // XXX these are probably only needed for WRITE files
         if (file->compression) {
             psTrace("psModules.camera", 7, "Setting compression for %s (%s)\n", file->filename, file->name);
@@ -761,6 +761,5 @@
         }
 
-        file->fits->floatType = file->floatType;
-	file->fits->bitpix = file->bitpix;
+        file->fits->options = psMemIncrRefCounter(file->options);
 
         // In some cases, we need to read the PHU after we've opened the file.  This happens for the images
