Index: /trunk/psModules/src/pmReadoutCombine.c
===================================================================
--- /trunk/psModules/src/pmReadoutCombine.c	(revision 2270)
+++ /trunk/psModules/src/pmReadoutCombine.c	(revision 2270)
@@ -0,0 +1,192 @@
+/** @file  pmReadoutCombine.c
+ *
+ *  This file will contain a module which will combine multiple readout images.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-11-03 22:10:37 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#include<stdio.h>
+#include<math.h>
+#include "pslib.h"
+// XXX: have Desonia do this correctly.
+#include "../../psLib/src/dataManip/psConstants.h"
+
+typedef struct
+{
+    psStats *stats;
+    unsigned int maskVal;
+    float fracHigh;
+    float fracLow;
+    int nKeep;
+}
+psCombineParams;
+
+
+int p_psDetermineNumBits(unsigned int data)
+{
+    int i;
+    unsigned int tmpData = data;
+    int numBits = 0;
+
+    for (i=0;i<sizeof(unsigned int);i++) {
+        if (0x0001 && tmpData) {
+            numBits++;
+        }
+        tmpData = tmpData >> 1;
+    }
+    return(numBits);
+}
+
+
+psImage *pmReadoutCombine(psImage *output,
+                          const psList *inputs,
+                          psCombineParams *params,
+                          const psVector *zero,
+                          const psVector *scale,
+                          bool applyZeroScale,
+                          float gain,
+                          float readnoise)
+{
+    PS_PTR_CHECK_NULL(inputs, NULL);
+    PS_PTR_CHECK_NULL(params, NULL);
+    //    unsigned int maskVal = params->maskVal;
+    psStats *stats = params->stats;
+    int i;
+    int j;
+    int numInputCols = -1;
+    int numInputRows = -1;
+    psListElem *tmpInput = NULL;
+    int numInputs = 0;
+    psReadout *tmpReadout;
+
+    //
+    // We step through each readout in the input image list.  If any readout is
+    // NULL, empty, or has the wrong type, we generate an error and return
+    // NULL.  If any readout is not the same size as any other image, we
+    // generate an error and return NULL.
+    tmpInput = (psListElem *) inputs->head;
+
+    while (NULL != tmpInput) {
+        tmpReadout = (psReadout *) tmpInput->data;
+        PS_READOUT_CHECK_NULL(tmpReadout, output);
+        PS_READOUT_CHECK_EMPTY(tmpReadout, output);
+        PS_READOUT_CHECK_TYPE(tmpReadout, PS_TYPE_F32, output);
+
+        if (numInputCols == -1) {
+            // XXX        numInputCols = tmpReadout->image->numCols + OFFSET??;
+            numInputCols = tmpReadout->image->numCols;
+        }
+        if (numInputRows == -1) {
+            // XXX            numInputRows = tmpReadout->image->numRows + OFFSET;
+            numInputRows = tmpReadout->image->numRows;
+        }
+
+        // XXX
+        if (numInputCols != tmpReadout->image->numCols) {
+            psError(__func__, "Image %d not same size as other input images (%d, %d)\n",
+                    tmpReadout->image->numRows, tmpReadout->image->numCols);
+            return(NULL);
+        }
+        // XXX
+        if (numInputRows != tmpReadout->image->numRows) {
+            psError(__func__, "Image %d not same size as other input images (%d, %d)\n",
+                    tmpReadout->image->numRows, tmpReadout->image->numCols);
+            return(NULL);
+        }
+
+        tmpInput = tmpInput->next;
+        numInputs++;
+    }
+
+    if (output == NULL) {
+        output = psImageAlloc(numInputCols, numInputRows, PS_TYPE_F32);
+    }
+
+
+    if (1 < p_psDetermineNumBits(params->stats->options)) {
+        psError(__func__, "Multiple statistical options have been requested.\n");
+        return(NULL);
+    }
+
+    psVector *tmpPixels = psVectorAlloc(numInputs, PS_TYPE_F32);
+    psVector *tmpPixelMask = psVectorAlloc(numInputs, PS_TYPE_U8);
+    psVector *tmpPixelMaskNKeep = psVectorAlloc(numInputs, PS_TYPE_U8);
+    psReadout **tmpReadouts = (psReadout **) psAlloc(numInputs * sizeof(psReadout *));
+    i = 0;
+    while (NULL != tmpInput) {
+        tmpReadouts[i] = (psReadout *) tmpInput->data;
+        tmpInput = tmpInput->next;
+        i++;
+    }
+
+    for (i = 0; i < output->numRows ; i++) {
+        for (j = 0; j < output->numCols ; j++) {
+            for (int r = 0; r < numInputs ; r++) {
+                //                if (i,j are valid for this readout) {
+                if (0) {
+                    //                    tmpPixels->data.F32[r] = WHATEVER;
+                    tmpPixelMask->data.U8[r] = 0;
+                } else {
+                    tmpPixels->data.F32[r] = 0.0;
+                    tmpPixelMask->data.U8[r] = 1;
+                }
+            }
+
+            // Determine how many pixels lie between fracLow and fracHigh.
+            int pixelCount = 0;
+            for (int r = 0; r < numInputs ; r++) {
+                if (tmpPixelMask->data.U8[r] == 0) {
+                    if ((params->fracLow <= tmpPixels->data.F32[r]) &&
+                            (params->fracHigh >= tmpPixels->data.F32[r])) {
+                        pixelCount++;
+                    }
+                }
+            }
+
+            // If more than params->nKeep pixels lie between the valid range,
+            // then loop through the pixels, and mask away any pixels outside
+            // that range.
+            if (pixelCount >= params->nKeep) {
+                for (int r = 0; r < numInputs ; r++) {
+                    if (tmpPixelMask->data.U8[r] == 0) {
+                        if ((params->fracLow <= tmpPixels->data.F32[r]) &&
+                                (params->fracHigh >= tmpPixels->data.F32[r])) {
+                            tmpPixelMaskNKeep->data.U8[r] = 0;
+                        } else {
+                            tmpPixelMaskNKeep->data.U8[r] = 1;
+                        }
+                    }
+                }
+            }
+
+            // Calculate the specified statistic on the stack of pixels.
+            stats = psVectorStats(stats,
+                                  tmpPixels,
+                                  tmpPixelMaskNKeep,
+                                  1);
+
+            // Set the pixel value in the output image to the stat value.
+            double statValue;
+            if (!p_psGetStatValue(stats, &statValue)) {
+                psError(__func__, "Could not determine stats value.\n");
+                return(NULL);
+            } else {
+                output->data.F32[i][j] = (float) statValue;
+            }
+        }
+    }
+
+    psFree(tmpPixels);
+    psFree(tmpPixels);
+    psFree(tmpPixelMask);
+    psFree(tmpPixelMaskNKeep);
+    psFree(tmpReadouts);
+
+    return(output);
+}
Index: /trunk/psModules/src/pmReadoutCombine.h
===================================================================
--- /trunk/psModules/src/pmReadoutCombine.h	(revision 2270)
+++ /trunk/psModules/src/pmReadoutCombine.h	(revision 2270)
@@ -0,0 +1,46 @@
+/** @file  pmReadoutCombine.h
+ *
+ *  This file will contain a module which will combine multiple readout images.
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-11-03 22:10:37 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+
+#if !defined(PM_READOUT_COMBINE_H)
+#define PM_READOUT_COMBINE_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include<stdio.h>
+#include<math.h>
+#include "pslib.h"
+// XXX: have Desonia do this correctly.
+#include "../../psLib/src/dataManip/psConstants.h"
+
+typedef struct
+{
+    psStats *stats;
+    unsigned int maskVal;
+    float fracHigh;
+    float fracLow;
+    int nKeep;
+}
+psCombineParams;
+
+psImage *pmReadoutCombine(psImage *output,
+                          const psList *inputs,
+                          psCombineParams *params,
+                          const psVector *zero,
+                          const psVector *scale,
+                          bool applyZeroScale,
+                          float gain,
+                          float readnoise);
+
+#endif
