Index: trunk/psModules/src/camera/pmReadoutStack.c
===================================================================
--- trunk/psModules/src/camera/pmReadoutStack.c	(revision 13872)
+++ trunk/psModules/src/camera/pmReadoutStack.c	(revision 13872)
@@ -0,0 +1,124 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pslib.h>
+
+#include "pmReadoutStack.h"
+
+
+bool pmReadoutUpdateSize(pmReadout *readout, int minCols, int minRows, int numCols, int numRows, bool mask)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+
+    if (readout->image) {
+        *(psS32*) &(readout->col0) = PS_MIN(minCols, readout->col0);
+        *(psS32*) &(readout->row0) = PS_MIN(minRows, readout->row0);
+    } else {
+        *(psS32*) &(readout->col0) = minCols;
+        *(psS32*) &(readout->row0) = minRows;
+    }
+
+    // (re-)Allocate the images
+    if (!readout->image) {
+        readout->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    }
+    if (readout->image->numCols < numCols || readout->image->numRows < numRows) {
+        // Generate the new output image by extending the current one, or making a whole new one
+        psImage *newImage = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+        psImageInit(newImage, 0.0);
+        psImageOverlaySection(newImage, readout->image, readout->col0, readout->row0, "=");
+        psFree(readout->image);
+        readout->image = newImage;
+    }
+
+    if (mask) {
+        if (!readout->mask) {
+            readout->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+        }
+        if (readout->mask->numCols < numCols || readout->mask->numRows < numRows) {
+            psImage *newMask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);
+            psImageInit(newMask, 0);
+            psImageOverlaySection(newMask, readout->mask, readout->col0, readout->row0, "=");
+            psFree(readout->mask);
+            readout->mask = newMask;
+        }
+    }
+
+    return true;
+}
+
+bool pmReadoutStackValidate(int *minInputColsPtr, int *maxInputColsPtr, int *minInputRowsPtr,
+                            int *maxInputRowsPtr, int *numColsPtr, int *numRowsPtr, const psArray *inputs)
+{
+    PS_ASSERT_ARRAY_NON_NULL(inputs, false);
+
+    // Step through each readout in the input image list to determine how big of an output image is needed to
+    // combine these input images.
+    int maxInputCols = 0;               // The largest input column value
+    int maxInputRows = 0;               // The largest input row value
+    int minInputCols = INT_MAX;         // The smallest input column value
+    int minInputRows = INT_MAX;         // The smallest input row value
+    int xSize = 0, ySize = 0;           // The size of the output image
+
+    int xMin = INT_MAX;
+    int yMin = INT_MAX;
+    int xMax = 0;
+    int yMax = 0;
+
+    bool valid = false;                 // Do we have a single valid input?
+    for (long i = 0; i < inputs->n; i++) {
+        pmReadout *readout = inputs->data[i]; // Readout of interest
+
+        if (!readout || !readout->image) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Input readout %ld is NULL or has NULL image.\n", i);
+            return false;
+        }
+
+        // use the trimsec to define the max full range of the output pixels
+        pmCell *cell = readout->parent; // The parent cell
+        bool mdok = true;       // Status of MD lookup
+        psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
+        if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) {
+            psWarning("CELL.TRIMSEC is not set for readout %ld --- ignored.\n", i);
+        } else {
+            xSize = PS_MAX(xSize, trimsec->x1 - trimsec->x0);
+            ySize = PS_MAX(ySize, trimsec->y1 - trimsec->y0);
+            xMin  = PS_MIN(xMin,  trimsec->x0);
+            xMax  = PS_MAX(xMax,  trimsec->x1);
+            yMin  = PS_MIN(yMin,  trimsec->y0);
+            yMax  = PS_MAX(yMax,  trimsec->y1);
+        }
+
+        valid = true;
+
+        // Range of pixels on output images
+        minInputCols = PS_MAX(xMin, PS_MIN(minInputCols, readout->col0));
+        maxInputCols = PS_MIN(xMax, PS_MAX(maxInputCols, readout->col0 + readout->image->numCols));
+        minInputRows = PS_MAX(yMin, PS_MIN(minInputRows, readout->row0));
+        maxInputRows = PS_MIN(yMax, PS_MAX(maxInputRows, readout->row0 + readout->image->numRows));
+        psTrace("psModules.camera", 7, "Readout %ld: offset %d,%d; size %dx%d\n", i,
+                readout->col0, readout->row0, readout->image->numCols, readout->image->numRows);
+    }
+
+    if (minInputColsPtr) {
+        *minInputColsPtr = minInputCols;
+    }
+    if (maxInputColsPtr) {
+        *maxInputColsPtr = maxInputCols;
+    }
+    if (minInputRowsPtr) {
+        *minInputRowsPtr = minInputRows;
+    }
+    if (maxInputRowsPtr) {
+        *maxInputRowsPtr = maxInputRows;
+    }
+    if (numColsPtr) {
+        *numColsPtr = xSize;
+    }
+    if (numRowsPtr) {
+        *numRowsPtr = ySize;
+    }
+
+    return valid;
+}
Index: trunk/psModules/src/camera/pmReadoutStack.h
===================================================================
--- trunk/psModules/src/camera/pmReadoutStack.h	(revision 13872)
+++ trunk/psModules/src/camera/pmReadoutStack.h	(revision 13872)
@@ -0,0 +1,22 @@
+#ifndef PM_READOUT_STACK_H
+#define PM_READOUT_STACK_H
+
+#include "pmHDU.h"
+#include "pmFPA.h"
+
+/// Update an output readout (for a stack) with the correct col0,row0 and the image size
+bool pmReadoutUpdateSize(pmReadout *readout, ///< Readout which to update
+                         int minCols, int minRows, ///< Minimum coordinates
+                         int numCols, int numRows, ///< Size of images
+                         bool mask      ///< Worry about the mask?
+    );
+
+/// Determine how large an output image is needed to combine the input readouts
+bool pmReadoutStackValidate(int *minInputColsPtr, int *maxInputColsPtr, ///< Min and max size in x
+                            int *minInputRowsPtr, int *maxInputRowsPtr, ///< Min and max size in y
+                            int *numColsPtr, int *numRowsPtr, ///< Size of image
+                            const psArray *inputs ///< Array of pmReadouts
+    );
+
+
+#endif
