Index: /trunk/psphot/src/psphotSourceSize.c
===================================================================
--- /trunk/psphot/src/psphotSourceSize.c	(revision 34200)
+++ /trunk/psphot/src/psphotSourceSize.c	(revision 34201)
@@ -18,4 +18,5 @@
     float sizeLimitCR;
     float magLimitCR;
+    int maxWindowCR;
 } psphotSourceSizeOptions;
 
@@ -26,5 +27,5 @@
 bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options);
 bool psphotSourceSelectCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options);
-bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal);
+bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal, int maxWindowCR);
 bool psphotMaskCosmicRayFootprintCheck (psArray *sources);
 int  psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh);
@@ -139,4 +140,9 @@
     if (!status) {
         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSPHOT.CRMASK.APPLY is not defined.");
+        return false;
+    }
+    options.maxWindowCR =  psMetadataLookupS32 (&status, recipe, "PSPHOT.CR.MAX.WINDOW");
+    if (!status) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSPHOT.CR.MAX.WINDOW is not defined.");
         return false;
     }
@@ -637,5 +643,5 @@
         psTrace("psphot", 6, "mask cosmic ray at %f, %f\n", source->peak->xf, source->peak->yf);
         if (options->applyCRmask) {
-            psphotMaskCosmicRay(readout, source, options->crMask);
+            psphotMaskCosmicRay(readout, source, options->crMask, options->maxWindowCR);
         } else {
             source->mode |= PM_SOURCE_MODE_CR_LIMIT;
@@ -677,5 +683,5 @@
 // does no repair or recovery of the CR pixels, it only masks them out.  My test code can be
 // found at /data/ipp031.0/watersc1/psphot.20091209/algo_check.c
-bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal) {
+bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal, int maxWindowCR) {
 
     // Get the actual images and information about the peak.
@@ -689,4 +695,16 @@
     int ys = footprint->bbox.y0;
     int ye = footprint->bbox.y1 + 1;
+
+    // We occasionally get very large footprints. When the footprint bounding box is large this function will
+    // do an incredible amount of work for no benefit.
+    // Limit the size of the area we examine.
+    if (xe - xs > maxWindowCR) {
+        xs = peak->x - maxWindowCR / 2;
+        xe = xs + maxWindowCR;
+    }
+    if (ye - ys > maxWindowCR) {
+        ys = peak->y - maxWindowCR / 2;
+        ye = ys + maxWindowCR;
+    }
 
     LIMIT_XRANGE(xs, mask);
@@ -731,7 +749,10 @@
     for (int i = 0; i < footprint->spans->n; i++) {
         pmSpan *sp = footprint->spans->data[i];
-        for (int j = sp->x0; j <= sp->x1; j++) {
-            int y = sp->y - ys;
-            int x = j - xs;
+        int y = sp->y - ys;
+        if (y < 0 || y >= mymask->numRows) {
+            // can we break if y >= numRows?
+            continue;
+        }
+        for (int x = PS_MAX(sp->x0 - xs, 0); x <= PS_MIN(sp->x1 - xs, mymask->numCols-1); x++) {
             mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= 0x01;
         }
@@ -873,5 +894,6 @@
 
 bool psphotMaskCosmicRayFootprintCheck (psArray *sources) {
-
+#ifdef CHECK_FOOTPRINTS
+    // This gets really expensive for complex images
     for (int i = 0; i < sources->n; i++) {
         pmSource *source = sources->data[i];
@@ -884,4 +906,5 @@
         }
     }
+#endif
     return true;
 }
