Index: /branches/eam_branches/ipp-20100823/ppStack/src/ppStackCombineFinal.c
===================================================================
--- /branches/eam_branches/ipp-20100823/ppStack/src/ppStackCombineFinal.c	(revision 29216)
+++ /branches/eam_branches/ipp-20100823/ppStack/src/ppStackCombineFinal.c	(revision 29217)
@@ -93,5 +93,13 @@
 
     // Sum covariance matrices
+    // the array may be defined, but no covariances actually supplied.
+    bool haveCovariances = false;
     if (covariances) {
+	for (int i = 0; i < covariances->n; i++) {
+	    haveCovariances |= (covariances->data[i] != NULL);
+	}
+    }
+
+    if (haveCovariances) {
         outRO->covariance = psImageCovarianceAverageWeighted(covariances, options->weightings);
     } else {
Index: /branches/eam_branches/ipp-20100823/ppStack/src/ppStackLoop.c
===================================================================
--- /branches/eam_branches/ipp-20100823/ppStack/src/ppStackLoop.c	(revision 29216)
+++ /branches/eam_branches/ipp-20100823/ppStack/src/ppStackLoop.c	(revision 29217)
@@ -204,4 +204,5 @@
 #if 1
     // Unconvolved stack --- it's cheap to calculate, compared to everything else!
+    // XXX unconvolved stack is currently using the convolved mask!  oops!
     if (options->convolve) {
         // Start threading
Index: /branches/eam_branches/ipp-20100823/ppStack/src/ppStackMatch.c
===================================================================
--- /branches/eam_branches/ipp-20100823/ppStack/src/ppStackMatch.c	(revision 29216)
+++ /branches/eam_branches/ipp-20100823/ppStack/src/ppStackMatch.c	(revision 29217)
@@ -68,5 +68,5 @@
 
     // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
-    psMetadataAddU8(psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskBad);
+    psMetadataAddImageMask(psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskBad);
 
     psImage *binned = psphotModelBackgroundReadoutNoFile(ro, config); // Binned background model
@@ -153,5 +153,6 @@
     int threads = psMetadataLookupS32(NULL, config->arguments, "-threads"); // Number of threads
 
-    if (!pmReadoutMaskNonfinite(readout, maskVal)) {
+    // Replaced pmReadoutMaskNonfinite with pmReadoutMaskInvalid (tests for already masked pixels)
+    if (!pmReadoutMaskInvalid(readout, maskVal, maskBad)) {
         psError(psErrorCodeLast(), false, "Unable to mask non-finite pixels in readout.");
         return false;
Index: /branches/eam_branches/ipp-20100823/ppStack/src/ppStackReadout.c
===================================================================
--- /branches/eam_branches/ipp-20100823/ppStack/src/ppStackReadout.c	(revision 29216)
+++ /branches/eam_branches/ipp-20100823/ppStack/src/ppStackReadout.c	(revision 29217)
@@ -130,10 +130,23 @@
     int kernelSize = psMetadataLookupS32(NULL, ppsub, "KERNEL.SIZE"); // Kernel half-size
 
-    psString maskValStr = psMetadataLookupStr(NULL, recipe, "MASK.VAL"); // Name of bits to mask going in
-    psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch
+    psString maskBadStr = psMetadataLookupStr(NULL, recipe, "MASK.VAL"); // Name of bits to mask for bad
+    psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
+
     psString maskSuspectStr = psMetadataLookupStr(NULL, recipe, "MASK.SUSPECT"); // Name of suspect mask bits
     psImageMaskType maskSuspect = pmConfigMaskGet(maskSuspectStr, config); // Suspect bits
-    psString maskBadStr = psMetadataLookupStr(NULL, recipe, "MASK.BAD"); // Name of bits to mask for bad
-    psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
+
+    bool status = false;
+    psImageMaskType maskBlank;
+    psString maskBlankStr = psMetadataLookupStr(&status, recipe, "MASK.BLANK"); // Name of bits to set for empty pixels
+    if (maskBlankStr) {
+      maskBlank = pmConfigMaskGet(maskBlankStr, config); // Bits to mask for bad pixels
+    } else {
+      maskBlankStr = psMetadataLookupStr(&status, recipe, "MASK.BAD"); // Old name for MASK.BLANK
+      if (maskBlankStr) {
+	maskBlank = pmConfigMaskGet(maskBlankStr, config); // Bits to mask for bad pixels
+      } else {
+	maskBlank = pmConfigMaskGet("BLANK", config); // Bits to mask for bad pixels
+      }
+    }
 
     int num = readouts->n;              // Number of inputs
@@ -157,5 +170,5 @@
     }
 
-    if (!pmStackCombine(outRO, NULL, stack, maskVal | maskBad, maskSuspect, maskBad, kernelSize, iter,
+    if (!pmStackCombine(outRO, NULL, stack, maskBad, maskSuspect, maskBlank, kernelSize, iter,
                         combineRej, combineSys, combineDiscard, useVariance, safe, false)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts with rejection.");
@@ -215,10 +228,23 @@
     bool safe = psMetadataLookupBool(&mdok, recipe, "SAFE"); // Be safe when combining small numbers of pixels
 
-    psString maskValStr = psMetadataLookupStr(NULL, recipe, "MASK.VAL"); // Name of bits to mask going in
-    psImageMaskType maskVal = pmConfigMaskGet(maskValStr, config); // Bits to mask going in to pmSubtractionMatch
+    psString maskBadStr = psMetadataLookupStr(NULL, recipe, "MASK.VAL"); // Name of bits to mask for bad
+    psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
+
     psString maskSuspectStr = psMetadataLookupStr(NULL, recipe, "MASK.SUSPECT"); // Name of suspect mask bits
     psImageMaskType maskSuspect = pmConfigMaskGet(maskSuspectStr, config); // Suspect bits
-    psString maskBadStr = psMetadataLookupStr(NULL, recipe, "MASK.BAD"); // Name of bits to mask for bad
-    psImageMaskType maskBad = pmConfigMaskGet(maskBadStr, config); // Bits to mask for bad pixels
+
+    bool status = false;
+    psImageMaskType maskBlank;
+    psString maskBlankStr = psMetadataLookupStr(&status, recipe, "MASK.BLANK"); // Name of bits to set for empty pixels
+    if (maskBlankStr) {
+      maskBlank = pmConfigMaskGet(maskBlankStr, config); // Bits to mask for bad pixels
+    } else {
+      maskBlankStr = psMetadataLookupStr(&status, recipe, "MASK.BAD"); // Old name for MASK.BLANK
+      if (maskBlankStr) {
+	maskBlank = pmConfigMaskGet(maskBlankStr, config); // Bits to mask for bad pixels
+      } else {
+	maskBlank = pmConfigMaskGet("BLANK", config); // Bits to mask for bad pixels
+      }
+    }
 
     int num = readouts->n;              // Number of inputs
@@ -257,5 +283,5 @@
     }
 
-    if (!pmStackCombine(outRO, expRO, stack, maskVal | maskBad, maskSuspect, maskBad, 0, iter, combineRej,
+    if (!pmStackCombine(outRO, expRO, stack, maskBad, maskSuspect, maskBlank, 0, iter, combineRej,
                         combineSys, combineDiscard, useVariance, safe, rejected)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts.");
