Index: /trunk/ppImage/src/ppImageDetrendReadout.c
===================================================================
--- /trunk/ppImage/src/ppImageDetrendReadout.c	(revision 13592)
+++ /trunk/ppImage/src/ppImageDetrendReadout.c	(revision 13593)
@@ -18,5 +18,5 @@
     // Masking on the basis of pixel value needs to be done before anything else, so the values are pristine.
     if (options->doMask || options->doShutter || options->doFlat || options->doPhotom) {
-        pmReadoutGenerateMask(input);
+        pmReadoutGenerateMask(input, options->satMask, options->badMask);
     }
     // apply the externally supplied mask to the input->mask pixels
@@ -68,5 +68,5 @@
     if (options->doFlat) {
         pmReadout *flat = pmFPAfileThisReadout(config->files, detview, "PPIMAGE.FLAT");
-        if (!pmFlatField(input, flat)) {
+        if (!pmFlatField(input, flat, options->flatMask)) {
             return false;
         }
Index: /trunk/ppImage/src/ppImageOptions.c
===================================================================
--- /trunk/ppImage/src/ppImageOptions.c	(revision 13592)
+++ /trunk/ppImage/src/ppImageOptions.c	(revision 13593)
@@ -24,5 +24,8 @@
     // default flags for various activities
     options->doMask     = false;        // Mask bad pixels
-    options->maskValue  = 0xff;         // Default mask value
+    options->maskValue  = 0x00;         // Default mask value
+    options->satMask    = 0x00;         // Saturated pixels
+    options->badMask    = 0x00;         // Bad pixels
+    options->flatMask   = 0x00;         // Bad flat pixels
 
     options->doNonLin   = false;        // Non-linearity correction
@@ -163,8 +166,12 @@
     // Mask recipe options
     options->doMask = psMetadataLookupBool(NULL, recipe, "MASK");
-    psMaskType maskValue = psMetadataLookupU8(&status, recipe, "MASK.VALUE");
+    const char *masks = psMetadataLookupStr(&status, recipe, "MASK.VALUE");
     if (status) {
-        options->maskValue = maskValue;
-    }
+        options->maskValue = pmConfigMask(masks, config);
+    }
+    options->satMask = pmConfigMask("SAT", config);
+    options->badMask = pmConfigMask("BAD", config);
+    options->flatMask = pmConfigMask("FLAT", config);
+
 
     options->doBias = psMetadataLookupBool(NULL, recipe, "BIAS");
Index: /trunk/ppImage/src/ppImageOptions.h
===================================================================
--- /trunk/ppImage/src/ppImageOptions.h	(revision 13592)
+++ /trunk/ppImage/src/ppImageOptions.h	(revision 13593)
@@ -6,4 +6,7 @@
     bool doMask;                        // Mask bad pixels
     psMaskType maskValue;               // apply this bit-mask to choose masked bits
+    psMaskType satMask;                 // Mask value to give saturated pixels
+    psMaskType badMask;                 // Mask value to give bad pixels
+    psMaskType flatMask;                // Mask value to give bad flat pixels
 
     bool doBias;                        // Bias subtraction
Index: /trunk/ppMerge/src/ppMergeCombine.c
===================================================================
--- /trunk/ppMerge/src/ppMergeCombine.c	(revision 13592)
+++ /trunk/ppMerge/src/ppMergeCombine.c	(revision 13593)
@@ -165,5 +165,5 @@
                         // If the mask value is set, we want to generate a mask
                         if (options->combine->maskVal) {
-                            pmReadoutSetMask(stack->data[i]);
+                            pmReadoutSetMask(stack->data[i], options->satMask, options->badMask);
                         }
 
Index: /trunk/ppMerge/src/ppMergeOptions.c
===================================================================
--- /trunk/ppMerge/src/ppMergeOptions.c	(revision 13592)
+++ /trunk/ppMerge/src/ppMergeOptions.c	(revision 13593)
@@ -59,4 +59,6 @@
     options->combine->maskVal = 0xff;
     options->combine->weights = false;
+    options->satMask = 0x00;
+    options->badMask = 0x00;
 
     return options;
@@ -141,5 +143,4 @@
     OPTION_PARSE(options->combine->fracLow,  recipe, "FRACLOW",        F32);
     OPTION_PARSE(options->combine->nKeep,    recipe, "NKEEP",          S32);
-    OPTION_PARSE(options->combine->maskVal,  recipe, "MASKVAL",        S32);
     OPTION_PARSE(options->combine->weights,  recipe, "WEIGHTS",        Bool);
     OPTION_PARSE(options->fringeNum,         recipe, "FRINGE.NUM",     S32);
@@ -153,4 +154,7 @@
     OPTION_PARSE(options->maskBad,           recipe, "MASK.BAD",       F32);
 
+    const char *masks = psMetadataLookupStr(NULL, recipe, "MASKVAL");
+    options->combine->maskVal = pmConfigMask(masks, config);
+
     options->combine->combine = parseStat(recipe, "COMBINE");
     options->mean             = parseStat(recipe, "MEAN");
@@ -238,5 +242,4 @@
     }
 
-
 #if 0
     // Or you can set them individually
@@ -249,4 +252,8 @@
     OPTION_PARSE(options->onOff, config->arguments, "-onoff", S32);
 
+    // Masking options
+    options->satMask = pmConfigMask("SAT", config);
+    options->badMask = pmConfigMask("BAD", config);
+
     return options;
 }
Index: /trunk/ppMerge/src/ppMergeOptions.h
===================================================================
--- /trunk/ppMerge/src/ppMergeOptions.h	(revision 13592)
+++ /trunk/ppMerge/src/ppMergeOptions.h	(revision 13593)
@@ -39,4 +39,6 @@
     ppOnOff onOff;                      // On/off pairs?
     pmCombineParams *combine;           // Combination parameters
+    psMaskType satMask;                 // Mask value for saturated pixels
+    psMaskType badMask;                 // Mask value for bad (low) pixels
 } ppMergeOptions;
 
Index: /trunk/ppStack/src/ppStackArguments.c
===================================================================
--- /trunk/ppStack/src/ppStackArguments.c	(revision 13592)
+++ /trunk/ppStack/src/ppStackArguments.c	(revision 13593)
@@ -64,4 +64,20 @@
 }
 
+// Get a mask value from the command-line or recipe, and add it to the arguments
+#define VALUE_ARG_RECIPE_MASK(ARGNAME, RECIPENAME) { \
+    bool mdok; \
+    const char *name = psMetadataLookupStr(&mdok, arguments, ARGNAME); \
+    if (!mdok || !name || strlen(name) == 0) { \
+        name = psMetadataLookupStr(NULL, recipe, RECIPENAME); \
+        if (!name) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find %s in recipe %s", \
+                RECIPENAME, PPSTACK_RECIPE); \
+            goto ERROR; \
+        } \
+    } \
+    psMaskType value = pmConfigMask(name, config); \
+    psMetadataAddU8(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, value); \
+}
+
 // Get a string value from the command-line and add it to the target
 static bool valueArgStr(pmConfig *config,      // Configuration
@@ -119,6 +135,6 @@
     VALUE_ARG_RECIPE_FLOAT("-convolve-rej", "CONVOLVE.REJ", F32);
     VALUE_ARG_RECIPE_FLOAT("-extent",       "EXTENT",       F32);
-    VALUE_ARG_RECIPE_INT("-mask-bad",       "MASK.BAD",     U8, 0);
-    VALUE_ARG_RECIPE_INT("-mask-blank",     "MASK.BLANK",   U8, 0);
+    VALUE_ARG_RECIPE_MASK("-mask-bad",      "MASK.BAD");
+    VALUE_ARG_RECIPE_MASK("-mask-blank",    "MASK.BLANK");
 
     psTrace("ppStack", 1, "Done reading command-line arguments\n");
Index: /trunk/ppSub/src/ppSubArguments.c
===================================================================
--- /trunk/ppSub/src/ppSubArguments.c	(revision 13592)
+++ /trunk/ppSub/src/ppSubArguments.c	(revision 13593)
@@ -57,4 +57,20 @@
     } \
     psMetadataAdd##TYPE(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, value); \
+}
+
+// Get a mask value from the command-line or recipe, and add it to the arguments
+#define VALUE_ARG_RECIPE_MASK(ARGNAME, RECIPENAME) { \
+    bool mdok; \
+    const char *name = psMetadataLookupStr(&mdok, arguments, ARGNAME); \
+    if (!mdok || !name || strlen(name) == 0) { \
+        name = psMetadataLookupStr(NULL, recipe, RECIPENAME); \
+        if (!name) { \
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find %s in recipe %s", \
+                RECIPENAME, PPSUB_RECIPE); \
+            goto ERROR; \
+        } \
+    } \
+    psMaskType value = pmConfigMask(name, config); \
+    psMetadataAddU8(config->arguments, PS_LIST_TAIL, RECIPENAME, 0, NULL, value); \
 }
 
@@ -200,6 +216,6 @@
     VALUE_ARG_RECIPE_INT("-iter",        "ITER",            S32, 0);
     VALUE_ARG_RECIPE_FLOAT("-rej",       "REJ",             F32);
-    VALUE_ARG_RECIPE_INT("-mask-bad",    "MASK.BAD",        U8, 0);
-    VALUE_ARG_RECIPE_INT("-mask-blank",  "MASK.BLANK",      U8, 0);
+    VALUE_ARG_RECIPE_MASK("-mask-bad",   "MASK.BAD");
+    VALUE_ARG_RECIPE_MASK("-mask-blank", "MASK.BLANK");
 
     vectorArgRecipe(config, arguments, "-isis-widths", recipe, "ISIS.WIDTHS", config->arguments, PS_TYPE_F32);
Index: /trunk/ppSub/src/ppSubReadout.c
===================================================================
--- /trunk/ppSub/src/ppSubReadout.c	(revision 13592)
+++ /trunk/ppSub/src/ppSubReadout.c	(revision 13593)
@@ -42,5 +42,8 @@
     psMaskType maskBlank = psMetadataLookupU8(NULL, config->arguments, "MASK.BLANK"); // Mask for blank reg.
 
-    if (!inRO->mask && !pmReadoutGenerateMask(inRO)) {
+    psMaskType maskSat = pmConfigMask("SAT", config); // Mask for saturated pixels
+    psMaskType maskLow = pmConfigMask("BAD", config); // Mask for bad (low) pixels
+
+    if (!inRO->mask && !pmReadoutGenerateMask(inRO, maskSat, maskLow)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to generate mask for input image");
         return false;
@@ -50,5 +53,5 @@
         return false;
     }
-    if (!refRO->mask && !pmReadoutGenerateMask(refRO)) {
+    if (!refRO->mask && !pmReadoutGenerateMask(refRO, maskSat, maskLow)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to generate mask for reference image");
         return false;
Index: /trunk/psphot/src/psphot.h
===================================================================
--- /trunk/psphot/src/psphot.h	(revision 13592)
+++ /trunk/psphot/src/psphot.h	(revision 13593)
@@ -57,5 +57,5 @@
 int             pmSourceSortByY (const void **a, const void **b);
 bool            psphotGrowthCurve (pmReadout *readout, pmPSF *psf, bool ignore);
-bool            psphotMaskReadout (pmReadout *readout, psMetadata *recipe);
+bool            psphotMaskReadout (pmReadout *readout, psMetadata *recipe, pmConfig *config);
 void            psphotSourceFreePixels (psArray *sources);
 
Index: /trunk/psphot/src/psphotMaskReadout.c
===================================================================
--- /trunk/psphot/src/psphotMaskReadout.c	(revision 13592)
+++ /trunk/psphot/src/psphotMaskReadout.c	(revision 13593)
@@ -1,6 +1,6 @@
 # include "psphotInternal.h"
 
-bool psphotMaskReadout (pmReadout *readout, psMetadata *recipe) {
-    
+bool psphotMaskReadout (pmReadout *readout, psMetadata *recipe, pmConfig *config) {
+
     bool status;
 
@@ -19,5 +19,5 @@
 
     // psImageKeepRegion assumes the region refers to the parent coordinates
-    psImageKeepRegion (readout->mask, keep, "OR", PM_MASK_BAD);
+    psImageKeepRegion (readout->mask, keep, "OR", pmConfigMask("BAD", config));
 
     return true;
Index: /trunk/psphot/src/psphotReadout.c
===================================================================
--- /trunk/psphot/src/psphotReadout.c	(revision 13592)
+++ /trunk/psphot/src/psphotReadout.c	(revision 13593)
@@ -24,5 +24,6 @@
 
     // generate mask & weight images if they don't already exit
-    if ((!readout->mask && !pmReadoutGenerateMask(readout)) ||
+    if ((!readout->mask && !pmReadoutGenerateMask(readout, pmConfigMask("SAT", config),
+                                                  pmConfigMask("BAD", config))) ||
         (!readout->weight && !pmReadoutGenerateWeight(readout, true))) {
         psError (PSPHOT_ERR_CONFIG, false, "trouble creating mask and/or weight");
@@ -37,5 +38,5 @@
 
     // I have a valid mask, now mask in the analysis region of interest
-    psphotMaskReadout (readout, recipe);
+    psphotMaskReadout (readout, recipe, config);
 
     // run a single-model test if desired
Index: /trunk/pswarp/src/pswarpArguments.c
===================================================================
--- /trunk/pswarp/src/pswarpArguments.c	(revision 13592)
+++ /trunk/pswarp/src/pswarpArguments.c	(revision 13593)
@@ -102,19 +102,27 @@
 
         // Get mask parameters
-        psMaskType maskIn = psMetadataLookupU8(&status, recipe, "MASK.IN"); // Mask for input data
-        if (!status) {
+        psMaskType maskIn, maskPoor, maskBad; // Mask values for input, "poor" and "bad" pixels
+
+        psString maskNames = psMetadataLookupStr(&status, recipe, "MASK.IN");
+         if (!status) {
             maskIn = 0x00;
             psWarning("MASK.IN is not set in the %s recipe --- defaulting to %x.", PSWARP_RECIPE, maskIn);
         }
-        psMaskType maskPoor = psMetadataLookupU8(&status, recipe, "MASK.POOR"); // Mask for "poor" warped data
+        maskIn = pmConfigMask(maskNames, config); // Mask for input data
+
+        maskNames = psMetadataLookupStr(&status, recipe, "MASK.POOR");
         if (!status) {
             maskPoor = 0x00;
             psWarning("MASK.POOR is not set in the %s recipe --- defaulting to %x.", PSWARP_RECIPE, maskPoor);
         }
-        psMaskType maskBad = psMetadataLookupU8(&status, recipe, "MASK.IN"); // Mask for bad warped data
+        maskPoor = pmConfigMask(maskNames, config); // Mask for "poor" warped data
+
+        maskNames = psMetadataLookupStr(&status, recipe, "MASK.BAD");
         if (!status) {
             maskBad = 0x00;
             psWarning("MASK.BAD is not set in the %s recipe --- defaulting to %x.", PSWARP_RECIPE, maskBad);
         }
+        maskBad = pmConfigMask(maskNames, config); // Mask for bad warped data
+
         float poorFrac = psMetadataLookupF32(&status, recipe, "POOR.FRAC"); // Frac of bad flux for a "poor"
         if (!status) {
