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);
