Index: trunk/ppStack/src/ppStackArguments.c
===================================================================
--- trunk/ppStack/src/ppStackArguments.c	(revision 16999)
+++ trunk/ppStack/src/ppStackArguments.c	(revision 17006)
@@ -129,9 +129,8 @@
     psMetadataAddS32(arguments, PS_LIST_TAIL, "-iter", 0, "Number of rejection iterations", 0);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-combine-rej", 0, "Combination rejection thresold (sigma)", NAN);
-    psMetadataAddF32(arguments, PS_LIST_TAIL, "-convolve-rej", 0, "Convolution rejection thresold (sigma)", NAN);
-    psMetadataAddF32(arguments, PS_LIST_TAIL, "-extent", 0, "Extent of convolution (sigma)", NAN);
     psMetadataAddU8(arguments,  PS_LIST_TAIL, "-mask-bad", 0, "Mask value for bad pixels", 0);
     psMetadataAddU8(arguments,  PS_LIST_TAIL, "-mask-blank", 0, "Mask value for blank region", 0);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-threshold-mask", 0, "Threshold for mask deconvolution", NAN);
+    psMetadataAddF32(arguments, PS_LIST_TAIL, "-image-rej", 0, "Pixel rejection fraction threshold for rejecting entire image", NAN);
     psMetadataAddS32(arguments, PS_LIST_TAIL, "-rows", 0, "Rows to read at once", 128);
     psMetadataAddBool(arguments, PS_LIST_TAIL, "-photometry", 0, "Do photometry on stacked image?", false);
@@ -180,9 +179,8 @@
     VALUE_ARG_RECIPE_INT("-iter",             "ITER",           S32, 0);
     VALUE_ARG_RECIPE_FLOAT("-combine-rej",    "COMBINE.REJ",    F32);
-    VALUE_ARG_RECIPE_FLOAT("-convolve-rej",   "CONVOLVE.REJ",   F32);
-    VALUE_ARG_RECIPE_FLOAT("-extent",         "EXTENT",         F32);
     VALUE_ARG_RECIPE_MASK("-mask-bad",        "MASK.BAD");
     VALUE_ARG_RECIPE_MASK("-mask-blank",      "MASK.BLANK");
     VALUE_ARG_RECIPE_FLOAT("-threshold-mask", "THRESHOLD.MASK", F32);
+    VALUE_ARG_RECIPE_FLOAT("-image-rej",      "IMAGE.REJ",      F32);
     VALUE_ARG_RECIPE_INT("-rows",             "ROWS",           S32, 0);
 
Index: trunk/ppStack/src/ppStackLoop.c
===================================================================
--- trunk/ppStack/src/ppStackLoop.c	(revision 16999)
+++ trunk/ppStack/src/ppStackLoop.c	(revision 17006)
@@ -183,4 +183,5 @@
 
     float threshold = psMetadataLookupF32(NULL, config->arguments, "THRESHOLD.MASK"); // Threshold for mask deconvolution
+    float imageRej = psMetadataLookupF32(NULL, config->arguments, "IMAGE.REJ"); // Maximum fraction of image to reject before rejecting entire image
 
     const char *statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); // Filename for statistics
@@ -472,5 +473,13 @@
                                              subKernels->data[i]); // Pixels to reject
             psFree(inspect);
-            psTrace("ppStack", 5, "%ld pixels rejected from image %d", reject->n, i);
+            float frac = reject->n / (float)(ro->image->numCols * ro->image->numRows); // Pixel fraction
+            psTrace("ppStack", 5, "%ld pixels rejected from image %d (%.1f%%)", reject->n, i, frac * 100.0);
+            if (frac > imageRej) {
+                psWarning("Image %d rejected completely because rejection fraction (%.3f) "
+                          "exceeds limit (%.3f)", i, frac, imageRej);
+                psFree(reject);
+                // reject == NULL means reject image completely
+                reject = NULL;
+            }
             rejected->data[i] = reject;
         }
@@ -484,4 +493,7 @@
             psTrace("ppStack", 2, "Final stack of chunk %d....\n", numChunk);
             for (int i = 0; i < num; i++) {
+                if (!rejected->data[i]) {
+                    continue;
+                }
                 pmReadout *readout = readouts->data[i];
                 assert(readout);
Index: trunk/ppStack/src/ppStackReadout.c
===================================================================
--- trunk/ppStack/src/ppStackReadout.c	(revision 16999)
+++ trunk/ppStack/src/ppStackReadout.c	(revision 17006)
@@ -66,5 +66,6 @@
     }
 
-    if (!pmStackCombine(outRO, stack, maskBad, maskBlank, kernelSize, iter, combineRej, useVariance, safe)) {
+    if (!pmStackCombine(outRO, stack, maskBad, maskBlank, kernelSize, iter, combineRej, true,
+                        useVariance, safe)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts with rejection.");
         psFree(stack);
@@ -85,5 +86,5 @@
     for (int i = 0; i < stack->n; i++) {
         pmStackData *data = stack->data[i]; // Data for this image
-        psImage *inspected = psPixelsToMask(NULL, data->pixels,
+        psImage *inspected = psPixelsToMask(NULL, data->inspect,
                                             psRegionSet(0, outRO->image->numCols - 1,
                                                         0, outRO->image->numRows - 1),
@@ -105,7 +106,6 @@
         psMetadataAddPtr(readout->analysis, PS_LIST_TAIL, PPSTACK_INSPECT_PIXELS,
                          PS_DATA_PIXELS | PS_META_DUPLICATE_OK, "Pixels to inspect from initial combination",
-                         data->pixels);
-    }
-
+                         data->inspect);
+    }
     psFree(stack);
 
@@ -144,5 +144,12 @@
     psList *fpaList = psListAlloc(NULL); // List of input FPAs, for concept averaging
     psList *cellList = psListAlloc(NULL); // List of input cells, for concept averaging
+    int numGood = num;                  // Number of good inputs: images that haven't been completely rejected
     for (int i = 0; i < num; i++) {
+        if (!rejected->data[i]) {
+            // Image completely rejected
+            numGood--;
+            continue;
+        }
+
         pmReadout *ro = readouts->data[i];
         assert(ro);
@@ -201,5 +208,5 @@
 
         pmStackData *data = pmStackDataAlloc(ro, weighting);
-        data->pixels = psMemIncrRefCounter(rejected->data[i]);
+        data->reject = psMemIncrRefCounter(rejected->data[i]);
         stack->data[i] = data;
     }
@@ -212,5 +219,5 @@
                 continue;
             }
-            psImage *reject = psPixelsToMask(NULL, data->pixels,
+            psImage *reject = psPixelsToMask(NULL, data->reject,
                                              psRegionSet(0, outRO->image->numCols - 1,
                                                          0, outRO->image->numRows - 1),
@@ -227,5 +234,5 @@
 #endif
 
-    if (!pmStackCombine(outRO, stack, maskBad, maskBlank, 0, 0, NAN, useVariance, false)) {
+    if (!pmStackCombine(outRO, stack, maskBad, maskBlank, 0, 0, NAN, numGood != num, useVariance, false)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts.");
         psFree(fpaList);
