Index: /trunk/pstamp/src/ppstampMakeStamp.c
===================================================================
--- /trunk/pstamp/src/ppstampMakeStamp.c	(revision 17046)
+++ /trunk/pstamp/src/ppstampMakeStamp.c	(revision 17047)
@@ -98,46 +98,76 @@
 }
 
-#ifdef notdef
-// update the ROI to account for any change in the coordinate system in the
-// mosaic process
-// THERE isn't any change. This is something I was trying to make the megacam
-// transforms come out correctly.
-static bool updateROI(ppstampOptions *options, pmFPAfile *mosaic, pmChip *mosaicChip)
-{
-    // set up the astrometry
-    pmHDU *hdu = pmHDUFromChip(mosaicChip);
-    PS_ASSERT_PTR_NON_NULL(hdu, 1)
-    PS_ASSERT_PTR_NON_NULL(hdu->header, 1)
-
-
-    if (!pmAstromReadWCS(mosaic->fpa, mosaicChip, hdu->header, 1.0)) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to Read WCS from mosaic, cannot proceed\n");
-        return false;
-    }
-    pmAstromObj *center = pmAstromObjAlloc();
-
-    center->sky->r = options->centerRA;
-    center->sky->d = options->centerDEC;
-    center->sky->rErr = 0;
-    center->sky->dErr = 0;
-
-    skyToChip(center, mosaic->fpa, mosaicChip);
-
-    int width = options->dX;
-    int height = options->dY;
-
-    fprintf(stderr, "ROI before: %s\n", psRegionToString(options->roi));
-
-    options->roi.x0 = center->chip->x - width/2;
-    options->roi.x1 = options->roi.x0 + width;
-    options->roi.y0 = center->chip->y - height/2;
-    options->roi.y1 = options->roi.y0 + height;
-
-    fprintf(stderr, "ROI after:  %s\n", psRegionToString(options->roi));
-
-
-    return true;
-}
-#endif
+// Extract pixels from an image. If part of the bounds of the region are
+// partially outside of the input those pixels are set to zero.
+psImage *extractStamp(psImage *image, psRegion region)
+{
+    int width  = region.x1 - region.x0;
+    int height = region.y1 - region.y0;
+
+    if (width < 0) {
+        return NULL;
+    }
+    if (height < 0) {
+        return NULL;
+    }
+
+    int srcX  = region.x0;
+    int srcY  = region.y0;
+    int lastX = region.x1;
+    int lastY = region.y1;
+    if (lastX > (image->col0 + image->numCols)) {
+        lastX = image->col0 + image->numCols;
+    }
+    if (lastY > (image->row0 + image->numRows)) {
+        lastY = image->row0 + image->numRows;
+    }
+        
+    int leftBlank = 0;
+    int dstX  = 0;
+    if (srcX < image->col0) {
+        leftBlank = image->col0 - srcX;
+        dstX += leftBlank;
+        srcX = 0;
+    }
+
+    int copyWidth  = lastX - srcX;
+    int rightBlank = width - copyWidth - leftBlank;
+    if (copyWidth <= 0) {
+        return NULL;
+    }
+
+    psImage *output = psImageAlloc(width, height, image->type.type);
+
+    psElemType  type = image->type.type;
+    psS32       elementSize =  PSELEMTYPE_SIZEOF(type);
+    int         copySize = copyWidth * elementSize;
+
+    for (int dstY=0 ; dstY < height; srcY++, dstY++) {
+        psU8 *pdst = output->data.U8[dstY];
+
+        if ((srcY < image->row0) || (srcY >= lastY)) {
+            // zero the row
+            memset(pdst, width*elementSize, 0);
+        } else {
+            psU8 *psrc = image->data.U8[srcY]  + (srcX * elementSize);
+
+            if (leftBlank) {
+                memset(pdst, leftBlank*elementSize, 0);
+            }
+
+            // copy copyWidth pixels from srcX,srcY to dstX, dstY
+            pdst += dstX*elementSize;
+            memcpy(pdst, psrc, copySize);
+
+            if (rightBlank) {
+                pdst += copyWidth * elementSize;
+                memset(pdst, rightBlank, 0);
+            }
+        }
+    }
+
+
+    return output;
+}
 
 // Build the postage stamp output file
@@ -169,21 +199,27 @@
     psMetadataAddS32(target->concepts, PS_LIST_TAIL, "CELL.YBIN", PS_META_REPLACE, "Binning in y", 1);
 
-
-    // we extract our postage stamp from a mosaic so that
-    // pmChipMosaic can handle the tricky bits of parity, binning, etc.
-    pmFPAfile *mosaic = ppstampBuildMosaic(config, input, view);
-    if (mosaic == NULL) {
-        return false;
-    }
-
-    // one cell one chip
-    pmFPAview *mosaicView = pmFPAviewAlloc(0);
-    mosaicView->chip = 0;
-    mosaicView->cell = 0;
+    pmFPAfile *srcFile;
+    pmFPAview *srcView = pmFPAviewAlloc(0);
+    if (psArrayLength(inChip->cells) > 1) {
+        // we extract our postage stamp from a mosaic so that
+        // we don't have to manage extracting from multiple cells
+        pmFPAfile *mosaic = ppstampBuildMosaic(config, input, view);
+        if (mosaic == NULL) {
+            return false;
+        }
+        srcFile = mosaic;
+        srcView->chip = 0;
+    } else {
+        srcFile = input;
+        *srcView = *view;
+    }
+
+    // At this point we know we have one cell
+    srcView->cell = 0;
 
     pmReadout *readout;
-    while ((readout = pmFPAviewNextReadout (mosaicView, mosaic->fpa, 1)) != NULL) {
+    while ((readout = pmFPAviewNextReadout (srcView, srcFile->fpa, 1)) != NULL) {
         if (!readout->data_exists) {
-            psError(PS_ERR_UNKNOWN, false, "no data in mosaic readout!\n");
+            psError(PS_ERR_UNKNOWN, false, "no data in input readout!\n");
             continue;
         }
@@ -200,48 +236,26 @@
         if (ppstampMegacamWorkaround) {
             // the coordinates of the mosaic are shifted 32 pixels from the chip
+            // TODO does this always apply? For example I doubt that applies to 
+            // skycells.
             extractRegion.x0 -= 32;
             extractRegion.x1 -= 32;
         }
-    
-        psImage *subsetImage = psImageSubset(readout->image, extractRegion);
-
-        if (subsetImage) {
-            // make a copy since we're going to change the image's internals
-            outReadout->image = psImageCopy(NULL, subsetImage, subsetImage->type.type);
-            psFree(subsetImage);
-            if (outReadout->image) {
-                // The image has inherited the subset's col0 and row0. We don't want this in
-                // our output so override the values.
-                // XXX put this into a function in psImage
-                // (What I really needed was a function that does
-                //     "create a copy of this portion of an image and return it as a new image with
-                //      origin 0,0 ")
-                P_PSIMAGE_SET_COL0(outReadout->image, 0);
-                P_PSIMAGE_SET_ROW0(outReadout->image, 0);
-
-                outReadout->data_exists = true;
-                outReadout->parent->data_exists = true;
-                outReadout->parent->parent->data_exists = true;
-                status = true;
-            } else {
-                psError(PS_ERR_UNKNOWN, false, "Copying of readout image failed.\n");
-                status = false;
-            }
-        } else {
-            psError(PS_ERR_UNKNOWN, false, "Image subset failed.\n");
+
+        outReadout->image = extractStamp(readout->image, extractRegion);
+        if (!outReadout->image) {
+            psError(PS_ERR_UNKNOWN, false, "failed to allocate create postage stamp image\n");
             status = false;
-        }
+            break;
+        }
+
+        outReadout->data_exists = true;
+        outReadout->parent->data_exists = true;
+        outReadout->parent->parent->data_exists = true;
+        status = true;
+
         psFree(outReadout); // drop reference
     }
 
-    // XXXX remove this or make writing the mosaic to a file a valid option
-    static bool writeMosaic = false;
-    if (writeMosaic) {
-        mosaic->save = true;
-        mosaicView->cell = -1;
-        pmFPAfileIOChecks(config, mosaicView, PM_FPA_AFTER);
-    }
-
-    psFree(mosaicView);
+    psFree(srcView);
 
     if (status) {
@@ -361,49 +375,4 @@
     options->roip.dY = options->roi.y1 - options->roi.y0;
 }
-
-#ifdef notdef
-// I'm not using this any more. We mosaic the chip before extracting the pixels
-// so we don't need to deal with cells at this level.
-
-// findCell
-// find cell on given chip that contains the region of interest
-// return the status of the overlap and if the cell completely contains the ROI 
-// set a pointer to reference the cell
-
-static ppstampOverlap findCell(pmFPAview *view, ppstampOptions *options, pmFPAfile *input,
-                                pmAstromObj *center, pmCell **ppCell)
-{
-    pmCell *cell;
-
-    view->cell = -1;
-    while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
-        psRegion *cellExtent = pmCellExtent(cell);
-        if (regionContainsPoint(cellExtent, center->chip)) {
-            if (regionContainsRegion(cellExtent, &options->roi)) {
-                *ppCell = cell;
-                psFree(cellExtent);
-                return PPSTAMP_ON;
-            } else {
-                fprintf(stderr, "ROI must be confined to single cell. Partial overlap cell %d\n",
-                    view->cell);
-                fprintf(stderr, "Partial Overlap cell %d\n", view->cell);
-                fprintf(stderr, "  ROI:         %s\n", psRegionToString(options->roi));
-                fprintf(stderr, "  Cell Extent: %s\n", psRegionToString(*cellExtent));
-                psFree(cellExtent);
-                return PPSTAMP_PARTIALLY_ON;
-            }
-        }
-        psFree(cellExtent);
-    }
-
-    // This shouldn't ever happen since ROI is on the chip, it must at least partially overlap
-    // one of the cells
-    psError(PS_ERR_PROGRAMMING, false, "findCell couldn't find a cell containing the center\n");
-
-    return PPSTAMP_OFF;
-}
-#endif
-
-
 
 // findROI
@@ -491,10 +460,9 @@
             returnval = PPSTAMP_ON;
         } else {
-            fprintf(stderr, "Partial Overlap chip %s\n", chipName);
-            fprintf(stderr, "ROI:         %s\n", psRegionToString(options->roi));
-            fprintf(stderr, "Chip Extent: %s\n", psRegionToString(*chipBounds));
+            psLogMsg("ppstampMakeStamp", 2, "Partial Overlap chip %s\n", chipName);
+            psLogMsg("ppstampMakeStamp", 2, "ROI:         %s\n", psRegionToString(options->roi));
+            psLogMsg("ppstampMakeStamp", 2, "Chip Extent: %s\n", psRegionToString(*chipBounds));
 
             returnval = PPSTAMP_PARTIALLY_ON;
-
         }
     }
@@ -550,15 +518,9 @@
             break;
         case PPSTAMP_ON:
+	case PPSTAMP_PARTIALLY_ON:
             returnval = makeStamp(config, options, input, chip, view);
             allDone = true;
             foundOverlap = true;
             break;
-	case PPSTAMP_PARTIALLY_ON:
-            psError(PS_ERR_UNKNOWN, false, "Region of interest must be confined to a single chip\n");
-            // XXX: perhaps print a helpful message about what coordinates would be valid
-            returnval = false;
-            allDone = true;
-            foundOverlap = true;
-            break;
         case PSTAMP_ERROR:
             returnval = false;
