Index: trunk/psLib/src/image/psImageExtraction.c
===================================================================
--- trunk/psLib/src/image/psImageExtraction.c	(revision 1267)
+++ trunk/psLib/src/image/psImageExtraction.c	(revision 1292)
@@ -9,6 +9,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-22 20:48:44 $
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-07-24 02:00:21 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -99,4 +99,5 @@
     if (input == NULL || input->data.V == NULL) {
         psError(__func__,"Can not copy image because input image or its pixel buffer is NULL.");
+        psFree(output);
         return NULL;
     }
@@ -105,4 +106,5 @@
         psError(__func__,"Can not copy image because given input and output "
                 "parameter reference the same psImage struct.");
+        psFree(output);
         return NULL;
     }
@@ -110,4 +112,5 @@
     if (input->type.dimen != PS_DIMEN_IMAGE) {
         psError(__func__,"Can not copy image because input image is not actually an image.");
+        psFree(output);
         return NULL;
     }
@@ -121,4 +124,5 @@
     if (inDatatype == PS_TYPE_PTR || type == PS_TYPE_PTR) {
         psError(__func__,"Can not copy image to/from a void* matrix");
+        psFree(output);
         return NULL;
     }
@@ -225,2 +229,172 @@
 }
 
+psVector* psImageSlice(psVector* out,
+                       const psImage* in,
+                       const psImage* restrict mask,
+                       unsigned int maskVal,
+                       unsigned int col,
+                       unsigned int row,
+                       unsigned int numCols,
+                       unsigned int numRows,
+                       psImageCutDirection direction,
+                       const psStats* stats)
+{
+    double statVal;
+    psStats* myStats;
+    psElemType type;
+    int inRows;
+    int inCols;
+    int delta = 1;
+    psF64* outData;
+
+    if (in == NULL || in->data.V == NULL) {
+        psError(__func__,"Input image can not be NULL.");
+        psFree(out);
+        return NULL;
+    }
+
+    type = in->type.type;
+    inRows = in->numRows;
+    inCols = in->numCols;
+
+    if (mask != NULL) {
+        if (inRows!=mask->numRows || inCols!=mask->numCols) {
+            psError(__func__,"The mask and image dimensions did not match (%dx%d vs %dx%d)",
+                    mask->numCols,mask->numRows,in->numCols,in->numRows);
+            psFree(out);
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            psError(__func__,"The mask datatype (%d) must be %s.",
+                    mask->type.type, PS_TYPE_MASK_NAME);
+            psFree(out);
+        }
+    }
+
+    if (row >= inRows || col >= inCols ||
+            col+numCols > in->numCols || row+numRows > in->numRows) {
+        psError(__func__,"The specified image region (%d,%d to %d,%d) is outside of image area (0,0 to %d,%d).",
+                col, row, col+numCols-1, row+numRows-1, in->numCols-1, in->numRows-1);
+        psFree(out);
+        return NULL;
+    }
+
+    // verify that the stats struct specifies a single stats operation
+    if (p_psGetStatValue(stats,&statVal) == false) {
+        psError(__func__,"The stat options didn't specify a single supported statistic type.");
+        psFree(out);
+        return NULL;
+    }
+
+    // since stats input is const, I need to create a 'scratch' stats struct
+    myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+
+    if (direction == PS_CUT_X_NEG || direction == PS_CUT_Y_NEG) {
+        delta = -1;
+    }
+
+    if (direction == PS_CUT_X_POS || direction == PS_CUT_X_NEG) {
+        psVector* imgVec = psVectorAlloc(numRows,type);
+        psVector* maskVec = NULL;
+        psMaskType* maskData = NULL;
+
+        // recycle output to make a proper sized/type output structure
+        // n.b. type is double as that is the type given for all stats in psStats.
+        out = psVectorRecycle(out,numCols,PS_TYPE_F64);
+        outData = out->data.F64;
+        if (delta < 0) {
+            outData += numCols - 1;
+        }
+
+        if (mask != NULL) {
+            maskVec = psVectorAlloc(numRows,mask->type.type);
+        }
+
+        #define PSIMAGE_CUT_VERTICAL(TYPE) \
+    case PS_TYPE_##TYPE: { \
+            ps##TYPE *imgVecData = imgVec->data.TYPE; \
+            psMaskType* maskVecData = NULL; \
+            if (maskVec != NULL) { \
+                maskVecData = maskVec->data.V; \
+            } \
+            for (int c=0;c<numCols;c++) { \
+                ps##TYPE *imgData = in->data.TYPE[row] + col + c; \
+                if (maskVec != NULL) { \
+                    maskData = (psMaskType*)(mask->data.V[row]) + col + c; \
+                } \
+                for (int r=0;r<numRows;r++) { \
+                    *(imgVecData++) = *imgData; \
+                    imgData += inCols; \
+                    if (maskVecData != NULL) { \
+                        *(maskVecData++) = *maskData; \
+                        maskData += inCols; \
+                    } \
+                } \
+                myStats = psVectorStats(myStats,imgVec,maskVec,maskVal); \
+                (void)p_psGetStatValue(myStats,&statVal); \
+                *outData = statVal; \
+                outData += delta; \
+            } \
+            break; \
+        }
+
+        switch (type) {
+            PSIMAGE_CUT_VERTICAL(U8);
+            PSIMAGE_CUT_VERTICAL(U16);
+            PSIMAGE_CUT_VERTICAL(U32);
+            PSIMAGE_CUT_VERTICAL(U64);
+            PSIMAGE_CUT_VERTICAL(S8);
+            PSIMAGE_CUT_VERTICAL(S16);
+            PSIMAGE_CUT_VERTICAL(S32);
+            PSIMAGE_CUT_VERTICAL(S64);
+            PSIMAGE_CUT_VERTICAL(F32);
+            PSIMAGE_CUT_VERTICAL(F64);
+            PSIMAGE_CUT_VERTICAL(C32);
+            PSIMAGE_CUT_VERTICAL(C64);
+        default:
+            psError(__func__,"Unsupported datatype (%d)",type);
+            psFree(out);
+            out = NULL;
+        }
+        psFree(imgVec);
+        psFree(maskVec);
+    } else { // Cut in Y direction
+        psVector* imgVec = NULL;
+        psVector* maskVec = NULL;
+        int elementSize = PSELEMTYPE_SIZEOF(type);
+
+        // fill in psVectors to fake out the statistics functions.
+        imgVec = psAlloc(sizeof(psVector));
+        imgVec->type = in->type;
+        imgVec->n = imgVec->nalloc = numCols;
+        if (mask != NULL) {
+            maskVec = psAlloc(sizeof(psVector));
+            maskVec->type = mask->type;
+            maskVec->n = maskVec->nalloc = numCols;
+        }
+
+        // recycle output to make a proper sized/type output structure
+        // n.b. type is double as that is the type given for all stats in psStats.
+        out = psVectorRecycle(out,numRows,PS_TYPE_F64);
+        outData = out->data.F64;
+        if (delta < 0) {
+            outData += numCols - 1;
+        }
+
+        for (int r=0;r<numRows;r++) {
+            // point the vector struct to the data to calculate the stats
+            imgVec->data.V = (void*)(in->data.U8[row+r]+col*elementSize);
+            if (maskVec!=NULL) {
+                maskVec->data.V = (void*)(mask->data.U8[row+r]+col*sizeof(psMaskType));
+            }
+            myStats = psVectorStats(myStats,imgVec,maskVec,maskVal);
+            (void)p_psGetStatValue(myStats,&statVal); // we know it works cause we tested it above
+            *outData = statVal;
+            outData += delta;
+        }
+    }
+
+    return out;
+}
+
