Index: /trunk/psLib/psLib.kdevses
===================================================================
--- /trunk/psLib/psLib.kdevses	(revision 1896)
+++ /trunk/psLib/psLib.kdevses	(revision 1897)
@@ -2,5 +2,41 @@
 <!DOCTYPE KDevPrjSession>
 <KDevPrjSession>
- <DocsAndViews NumberOfDocuments="0" />
+ <DocsAndViews NumberOfDocuments="7" >
+  <Doc0 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImageExtraction.c" >
+   <View0 line="723" Type="???" >
+    <AdditionalSettings Top="1" Width="1123" Attach="1" Height="738" Left="1" MinMaxMode="0" />
+   </View0>
+  </Doc0>
+  <Doc1 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImageErrors.dat" >
+   <View0 line="27" Type="???" >
+    <AdditionalSettings Top="1" Width="1123" Attach="1" Height="736" Left="1" MinMaxMode="0" />
+   </View0>
+  </Doc1>
+  <Doc2 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImageExtraction.h" >
+   <View0 line="146" Type="???" >
+    <AdditionalSettings Top="1" Width="1123" Attach="1" Height="738" Left="1" MinMaxMode="0" />
+   </View0>
+  </Doc2>
+  <Doc3 context="" NumberOfViews="1" URL="man:/hypot" >
+   <View0 Type="???" >
+    <AdditionalSettings Top="1" Width="1123" Attach="1" Height="736" Left="1" MinMaxMode="0" />
+   </View0>
+  </Doc3>
+  <Doc4 context="" NumberOfViews="1" URL="man:/usr/share/man/man3/hypot.3.gz" >
+   <View0 Type="???" >
+    <AdditionalSettings Top="1" Width="1123" Attach="1" Height="736" Left="1" MinMaxMode="0" />
+   </View0>
+  </Doc4>
+  <Doc5 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImage.c" >
+   <View0 line="482" Type="???" >
+    <AdditionalSettings Top="1" Width="1123" Attach="1" Height="738" Left="1" MinMaxMode="0" />
+   </View0>
+  </Doc5>
+  <Doc6 NumberOfViews="1" URL="file:/home/desonia/psLib/src/image/psImage.h" >
+   <View0 line="177" Type="???" >
+    <AdditionalSettings Top="1" Width="1123" Attach="1" Height="738" Left="1" MinMaxMode="0" />
+   </View0>
+  </Doc6>
+ </DocsAndViews>
  <pluginList>
   <kdevbookmarks>
Index: /trunk/psLib/src/collections/psVector.c
===================================================================
--- /trunk/psLib/src/collections/psVector.c	(revision 1896)
+++ /trunk/psLib/src/collections/psVector.c	(revision 1897)
@@ -10,6 +10,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-09-16 23:47:43 $
+*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-09-25 02:06:12 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -110,4 +110,108 @@
 }
 
+psVector* psVectorCopy(psVector* out, const psVector* in, psElemType type)
+{
+    if (in == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psVectorSort",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psVector_SORT_NULL);
+        psFree(out);
+        return NULL;
+    }
+
+    int nElements = in->n;
+
+    out = psVectorRecycle(out, nElements, type);
+
+    #define PSVECTOR_COPY(INTYPE,OUTTYPE) { \
+        ps##INTYPE *inVec = in->data.INTYPE; \
+        ps##OUTTYPE *outVec = out->data.OUTTYPE; \
+        for (int col=0;col<nElements;col++) { \
+            *(outVec++) = *(inVec++); \
+        } \
+    }
+
+    #define PSVECTOR_COPY_CASE(OUTTYPE) \
+case PS_TYPE_##OUTTYPE: { \
+        switch (in->type.type) { \
+        case PS_TYPE_S8: \
+            PSVECTOR_COPY(S8,OUTTYPE); \
+            break; \
+        case PS_TYPE_S16: \
+            PSVECTOR_COPY(S16,OUTTYPE); \
+            break; \
+        case PS_TYPE_S32: \
+            PSVECTOR_COPY(S32,OUTTYPE); \
+            break; \
+        case PS_TYPE_S64: \
+            PSVECTOR_COPY(S64,OUTTYPE); \
+            break; \
+        case PS_TYPE_U8: \
+            PSVECTOR_COPY(U8,OUTTYPE); \
+            break; \
+        case PS_TYPE_U16: \
+            PSVECTOR_COPY(U16,OUTTYPE); \
+            break; \
+        case PS_TYPE_U32: \
+            PSVECTOR_COPY(U32,OUTTYPE); \
+            break; \
+        case PS_TYPE_U64: \
+            PSVECTOR_COPY(U64,OUTTYPE); \
+            break; \
+        case PS_TYPE_F32: \
+            PSVECTOR_COPY(F32,OUTTYPE); \
+            break; \
+        case PS_TYPE_F64: \
+            PSVECTOR_COPY(F64,OUTTYPE); \
+            break; \
+        case PS_TYPE_C32: \
+            PSVECTOR_COPY(C32,OUTTYPE); \
+            break; \
+        case PS_TYPE_C64: \
+            PSVECTOR_COPY(C64,OUTTYPE); \
+            break; \
+        default: { \
+                char* typeStr; \
+                PS_TYPE_NAME(typeStr,type); \
+                psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCopy", \
+                           PS_ERR_BAD_PARAMETER_TYPE, true, \
+                           PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE, \
+                           typeStr); \
+                psFree(out); \
+            } \
+        } \
+        break; \
+    }
+
+    switch (type) {
+        PSVECTOR_COPY_CASE(S8);
+        PSVECTOR_COPY_CASE(S16);
+        PSVECTOR_COPY_CASE(S32);
+        PSVECTOR_COPY_CASE(S64);
+        PSVECTOR_COPY_CASE(U8);
+        PSVECTOR_COPY_CASE(U16);
+        PSVECTOR_COPY_CASE(U32);
+        PSVECTOR_COPY_CASE(U64);
+        PSVECTOR_COPY_CASE(F32);
+        PSVECTOR_COPY_CASE(F64);
+        PSVECTOR_COPY_CASE(C32);
+        PSVECTOR_COPY_CASE(C64);
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCopy",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE,
+                       typeStr);
+            psFree(out);
+
+            break;
+        }
+    }
+    return out;
+
+
+}
+
 psVector* psVectorSort(psVector* restrict outVector, const psVector* restrict inVector)
 {
Index: /trunk/psLib/src/collections/psVector.h
===================================================================
--- /trunk/psLib/src/collections/psVector.h	(revision 1896)
+++ /trunk/psLib/src/collections/psVector.h	(revision 1897)
@@ -12,6 +12,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-08-11 20:17:35 $
+ *  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -105,4 +105,18 @@
 );
 
+/** Copy a vector, converting types.
+ *
+ *  Performs a deep copy of the elements of one psVector to a new psVector, 
+ *  converting numeric types to a specified type.
+ *
+ * @return psVector*       Pointer to resulting psVector.
+ *
+ */
+psVector* psVectorCopy(
+    psVector* out,                     ///< if non-NULL, a psVector to recycle
+    const psVector* in,                ///< the vector to copy.
+    psElemType type                    ///< the data type of the resulting psVector
+);
+
 /** Sort an array of floats.
  *
Index: /trunk/psLib/src/image/psImage.c
===================================================================
--- /trunk/psLib/src/image/psImage.c	(revision 1896)
+++ /trunk/psLib/src/image/psImage.c	(revision 1897)
@@ -10,6 +10,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.45 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-21 23:15:04 $
+ *  @version $Revision: 1.46 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -199,4 +199,6 @@
                               float x,
                               float y,
+                              const psImage* mask,
+                              unsigned int maskVal,
                               psC64 unexposedValue,
                               psImageInterpolateMode mode)
@@ -214,9 +216,19 @@
     switch (mode) {                                                  \
     case PS_INTERPOLATE_FLAT:                                        \
-        return p_psImagePixelInterpolateFLAT_##TYPE(input, x, y,     \
+        return p_psImagePixelInterpolateFLAT_##TYPE(                 \
+                input,                                               \
+                x,                                                   \
+                y,                                                   \
+                mask,                                                \
+                maskVal,                                             \
                 unexposedValue);                                     \
         break;                                                       \
     case PS_INTERPOLATE_BILINEAR:                                    \
-        return p_psImagePixelInterpolateBILINEAR_##TYPE(input,x,y,   \
+        return p_psImagePixelInterpolateBILINEAR_##TYPE(             \
+                input,                                               \
+                x,                                                   \
+                y,                                                   \
+                mask,                                                \
+                maskVal,                                             \
                 unexposedValue);                                     \
         break;                                                       \
@@ -259,4 +271,6 @@
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psF64 unexposedValue) \
 { \
@@ -269,5 +283,7 @@
             (intX > lastX) || \
             (intY < 0) || \
-            (intY > lastY)) { \
+            (intY > lastY) || \
+            ( (mask!=NULL) && \
+              ((mask->data.PS_TYPE_MASK_DATA[intY][intX] & maskVal) != 0) ) ) { \
         return unexposedValue; \
     } \
@@ -280,4 +296,6 @@
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psC64 unexposedValue) \
 { \
@@ -290,5 +308,7 @@
             (intX > lastX) || \
             (intY < 0) || \
-            (intY > lastY)) { \
+            (intY > lastY) || \
+            ( (mask!=NULL) && \
+              ((mask->data.PS_TYPE_MASK_DATA[intY][intX] & maskVal) != 0) ) ) { \
         return unexposedValue; \
     } \
@@ -314,109 +334,186 @@
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psF64 unexposedValue) \
 { \
     double floorX = floor((psF64)(x) - 0.5); \
     double floorY = floor((psF64)(y) - 0.5); \
-    double fracX = x - 0.5 - floorX; \
-    double fracY = y - 0.5 - floorY; \
+    psF64 fracX = x - 0.5 - floorX; \
+    psF64 fracY = y - 0.5 - floorY; \
     int intFloorX = (int) floorX; \
     int intFloorY = (int) floorY; \
     int lastX = input->numCols - 1; \
     int lastY = input->numRows - 1; \
-    double rx = 0.0; \
-    psF64 pixel = 0.0; \
-    ps##TYPE* currentRow; \
-    ps##TYPE* nextRow; \
-    \
-    if ((intFloorX < 0) || \
-            (intFloorX > lastX) || \
-            (intFloorY < 0) || \
-            (intFloorY > lastY)) { \
-        return unexposedValue; \
-    } \
-    \
-    currentRow = input->data.TYPE[intFloorY]; \
-    if (intFloorY == lastY) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorX < lastX) { \
-            pixel+= fracY * ((psF64)currentRow[intFloorX+1] - \
-                             (psF64)currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    nextRow = input->data.TYPE[intFloorY+1]; \
-    if (intFloorX == lastX) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorY < lastY) { \
-            pixel+= fracX * ((psF64)nextRow[intFloorX] - \
-                             (psF64)currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    \
-    rx = currentRow[intFloorX] + \
-         fracX * ((psF64)currentRow[intFloorX+1] - \
-                  (psF64)currentRow[intFloorX]); \
-    \
-    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
-                          fracX * ((psF64)nextRow[intFloorX+1] - \
-                                   (psF64)nextRow[intFloorX]) - rx); \
-    \
-    return(pixel); \
-}
+    ps##TYPE V00; \
+    ps##TYPE V01; \
+    ps##TYPE V10; \
+    ps##TYPE V11; \
+    bool valid00 = false; \
+    bool valid01 = false; \
+    bool valid10 = false; \
+    bool valid11 = false; \
+    \
+    if (intFloorY >= 0 && intFloorY <= lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V00 = input->data.TYPE[intFloorY][intFloorX]; \
+            valid00 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V10 = input->data.TYPE[intFloorY][intFloorX+1]; \
+            valid10 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    if (intFloorY >= -1 && intFloorY < lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V01 = input->data.TYPE[intFloorY+1][intFloorX]; \
+            valid01 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V11 = input->data.TYPE[intFloorY+1][intFloorX+1]; \
+            valid11 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    \
+    /* cover likely case of all pixels being valid more efficiently */  \
+    if (valid00 && valid10 && valid01 && valid11) { \
+        /* formula from the ADD */ \
+        psF64 rx = V00 + (V10-V00)*fracX; \
+        return (rx + (V01 + (V11 - V01) * fracX - rx) * fracY); \
+    } \
+    \
+    /* OK, at least one pixel is not valid - need to do it piecemeal */ \
+    \
+    psF64 V0; \
+    bool valid0 = true; \
+    if (valid00 && valid10) { \
+        V0 = V00*(1-fracX)+V10*fracX; \
+    } else if (valid00) { \
+        V0 = V00; \
+    } else if (valid10) { \
+        V0 = V10; \
+    } else { \
+        valid0 = false; \
+    } \
+    \
+    psF64 V1; \
+    bool valid1 = true; \
+    if (valid01 && valid11) { \
+        V0 = V01*(1-fracX)+V11*fracX; \
+    } else if (valid01) { \
+        V0 = V01; \
+    } else if (valid11) { \
+        V0 = V11; \
+    } else { \
+        valid1 = false; \
+    } \
+    \
+    if (valid0 && valid1) { \
+        return ( V0*(1-fracY) + V1*fracY ); \
+    } else if (valid0) { \
+        return V0; \
+    } else if (valid1) { \
+        return V1; \
+    } \
+    \
+    return unexposedValue; \
+}
+
 #define PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(TYPE) \
 inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE(const psImage* input, \
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psC64 unexposedValue) \
 { \
     double floorX = floor((psF64)(x) - 0.5); \
     double floorY = floor((psF64)(y) - 0.5); \
-    double fracX = x - 0.5 - floorX; \
-    double fracY = y - 0.5 - floorY; \
+    psF64 fracX = x - 0.5 - floorX; \
+    psF64 fracY = y - 0.5 - floorY; \
     int intFloorX = (int) floorX; \
     int intFloorY = (int) floorY; \
     int lastX = input->numCols - 1; \
     int lastY = input->numRows - 1; \
-    double rx = 0.0; \
-    psC64 pixel = 0.0; \
-    ps##TYPE* currentRow; \
-    ps##TYPE* nextRow; \
-    \
-    if ((intFloorX < 0) || \
-            (intFloorX > lastX) || \
-            (intFloorY < 0) || \
-            (intFloorY > lastY)) { \
-        return unexposedValue; \
-    } \
-    \
-    currentRow = input->data.TYPE[intFloorY]; \
-    if (intFloorY == lastY) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorX < lastX) { \
-            pixel+= fracY * (currentRow[intFloorX+1] - \
-                             currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    nextRow = input->data.TYPE[intFloorY+1]; \
-    if (intFloorX == lastX) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorY < lastY) { \
-            pixel+= fracX * (nextRow[intFloorX] - \
-                             currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    \
-    rx = currentRow[intFloorX] + \
-         fracX * (currentRow[intFloorX+1] - \
-                  currentRow[intFloorX]); \
-    \
-    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
-                          fracX * (nextRow[intFloorX+1] - \
-                                   nextRow[intFloorX]) - rx); \
-    \
-    return(pixel); \
+    ps##TYPE V00; \
+    ps##TYPE V01; \
+    ps##TYPE V10; \
+    ps##TYPE V11; \
+    bool valid00 = false; \
+    bool valid01 = false; \
+    bool valid10 = false; \
+    bool valid11 = false; \
+    \
+    if (intFloorY >= 0 && intFloorY <= lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V00 = input->data.TYPE[intFloorY][intFloorX]; \
+            valid00 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V10 = input->data.TYPE[intFloorY][intFloorX+1]; \
+            valid10 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    if (intFloorY >= -1 && intFloorY < lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V01 = input->data.TYPE[intFloorY+1][intFloorX]; \
+            valid01 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V11 = input->data.TYPE[intFloorY+1][intFloorX+1]; \
+            valid11 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    \
+    /* cover likely case of all pixels being valid */  \
+    if (valid00 && valid10 && valid01 && valid11) { \
+        /* formula from the ADD */ \
+        psC64 rx = V00 + (V10-V00)*fracX; \
+        return (rx + (V01 + (V11 - V01) * fracX - rx) * fracY); \
+    } \
+    \
+    /* OK, at least one pixel is not valid - need to do it piecemeal */ \
+    \
+    psC64 V0; \
+    bool valid0 = true; \
+    if (valid00 && valid10) { \
+        V0 = V00*(1-fracX)+V10*fracX; \
+    } else if (valid00) { \
+        V0 = V00; \
+    } else if (valid10) { \
+        V0 = V10; \
+    } else { \
+        valid0 = false; \
+    } \
+    \
+    psC64 V1; \
+    bool valid1 = true; \
+    if (valid01 && valid11) { \
+        V0 = V01*(1-fracX)+V11*fracX; \
+    } else if (valid01) { \
+        V0 = V01; \
+    } else if (valid11) { \
+        V0 = V11; \
+    } else { \
+        valid1 = false; \
+    } \
+    \
+    if (valid0 && valid1) { \
+        return ( V0*(1-fracY) + V1*fracY ); \
+    } else if (valid0) { \
+        return V0; \
+    } else if (valid1) { \
+        return V1; \
+    } \
+    \
+    return unexposedValue; \
 }
 
Index: /trunk/psLib/src/image/psImage.h
===================================================================
--- /trunk/psLib/src/image/psImage.h	(revision 1896)
+++ /trunk/psLib/src/image/psImage.h	(revision 1897)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-21 19:51:41 $
+ *  @version $Revision: 1.37 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -118,4 +118,6 @@
     float x,                           ///< column location to derive value of
     float y,                           ///< row location ot derive value of
+    const psImage* mask,               ///< if not NULL, the mask of the input image
+    unsigned int maskVal,              ///< the mask value
     psC64 unexposedValue,              ///< return value if x,y location is not in image.
     psImageInterpolateMode mode        ///< interpolation mode
@@ -124,28 +126,36 @@
 #define p_psImagePixelInterpolateFcns(TYPE) \
 inline psF64 p_psImagePixelInterpolateFLAT_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psF64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psF64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                  ); \
 inline psF64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psF64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psF64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                      );
 
 #define p_psImagePixelInterpolateComplexFcns(TYPE) \
 inline psC64 p_psImagePixelInterpolateFLAT_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psC64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psC64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                  ); \
 inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psC64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psC64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                      );
 
@@ -162,4 +172,6 @@
 p_psImagePixelInterpolateComplexFcns(C32)
 p_psImagePixelInterpolateComplexFcns(C64)
+
 /// @}
+
 #endif
Index: /trunk/psLib/src/image/psImageErrors.dat
===================================================================
--- /trunk/psLib/src/image/psImageErrors.dat	(revision 1896)
+++ /trunk/psLib/src/image/psImageErrors.dat	(revision 1897)
@@ -26,4 +26,9 @@
 psImage_SLICE_DIRECTION_INVALID        Specified slice direction, %d, is invalid.
 psImage_PARAMETER_OUTOF_TYPERANGE      Specified %s value, %g, is outside of psImage type's range (%s: %g to %g).
+psImage_nSamples_TOOSMALL              Specified number of samples, %d, must be greater than 1 to make a line.
+psImage_LINE_NOT_IN_IMAGE              Specified line, (%f,%f)->(%f,%f), does not entirely lie in psImage's boundaries, [0:%d,0:%d].
+psImage_RADII_VECTOR_NULL              Specified radii vector can not be NULL.
+psImage_CENTER_NOT_IN_IMAGE            Specified center, (%d,%d), is outside of the psImage boundaries, [0:%d,0:%d].
+psImage_RADII_VECTOR_TOOSMALL          Input radii vector size, %d, can not be less than 2.
 #
 psImageFFT_IMAGE_TYPE_UNSUPPORTED      Input psImage type (%s) is not supported. Valid image types are psF32 and psC32.
Index: /trunk/psLib/src/image/psImageErrors.h
===================================================================
--- /trunk/psLib/src/image/psImageErrors.h	(revision 1896)
+++ /trunk/psLib/src/image/psImageErrors.h	(revision 1897)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-23 18:31:49 $
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -48,4 +48,9 @@
 #define PS_ERRORTEXT_psImage_SLICE_DIRECTION_INVALID "Specified slice direction, %d, is invalid."
 #define PS_ERRORTEXT_psImage_PARAMETER_OUTOF_TYPERANGE "Specified %s value, %g, is outside of psImage type's range (%s: %g to %g)."
+#define PS_ERRORTEXT_psImage_nSamples_TOOSMALL "Specified number of samples, %d, must be greater than 1 to make a line."
+#define PS_ERRORTEXT_psImage_LINE_NOT_IN_IMAGE "Specified line, (%f,%f)->(%f,%f), does not entirely lie in psImage's boundaries, [0:%d,0:%d]."
+#define PS_ERRORTEXT_psImage_RADII_VECTOR_NULL "Specified radii vector can not be NULL."
+#define PS_ERRORTEXT_psImage_CENTER_NOT_IN_IMAGE "Specified center, (%d,%d), is outside of the psImage boundaries, [0:%d,0:%d]."
+#define PS_ERRORTEXT_psImage_RADII_VECTOR_TOOSMALL "Input radii vector size, %d, can not be less than 2."
 #define PS_ERRORTEXT_psImageFFT_IMAGE_TYPE_UNSUPPORTED "Input psImage type (%s) is not supported. Valid image types are psF32 and psC32."
 #define PS_ERRORTEXT_psImageFFT_REVERSE_NOT_COMPLEX "Input psImage (%s) is not complex.  Reverse FFT operation requires a complex psImage input."
Index: /trunk/psLib/src/image/psImageExtraction.c
===================================================================
--- /trunk/psLib/src/image/psImageExtraction.c	(revision 1896)
+++ /trunk/psLib/src/image/psImageExtraction.c	(revision 1897)
@@ -10,6 +10,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-09-23 18:31:49 $
+*  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-09-25 02:06:12 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -609,6 +609,7 @@
 
 psVector* psImageCut(psVector* out,
-                     psVector* coords,
-                     const psImage* input,
+                     psVector* cutCols,
+                     psVector* cutRows,
+                     const psImage* in,
                      const psImage* restrict mask,
                      unsigned int maskVal,
@@ -620,10 +621,125 @@
                      psImageInterpolateMode mode)
 {
-
-    return NULL;
+    if (in == NULL || in->data.V == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_IMAGE_NULL);
+        psFree(out);
+        return NULL;
+    }
+    int numCols = in->numCols;
+    int numRows = in->numRows;
+
+    if (nSamples < 2) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_nSamples_TOOSMALL,
+                   nSamples);
+        psFree(out);
+        return NULL;
+    }
+
+    if (startCol < 0 || startCol >= numCols ||
+            startRow < 0 || startRow >= numRows ||
+            endCol < 0 || endCol >= numCols ||
+            endRow < 0 || endRow >= numRows) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_LINE_NOT_IN_IMAGE,
+                   startCol,startRow,endCol,endRow,
+                   numCols,numRows);
+        psFree(out);
+    }
+
+    if (mask != NULL) {
+        if (numRows != mask->numRows || numCols != mask->numCols) {
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                       PS_ERR_BAD_PARAMETER_VALUE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_SIZE,
+                       mask->numCols,mask->numRows,
+                       numCols, numRows);
+            psFree(out);
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_TYPE,
+                       typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+        }
+    }
+
+    //resize the vectors for the coordinate output
+    psF32* cutColsData = NULL;
+    psF32* cutRowsData = NULL;
+    if (cutCols != NULL) {
+        (void)psVectorRecycle(cutCols, nSamples, PS_TYPE_F32);
+        cutColsData = cutCols->data.F32;
+    }
+    if (cutRows != NULL) {
+        (void)psVectorRecycle(cutRows, nSamples, PS_TYPE_F32);
+        cutRowsData = cutRows->data.F32;
+    }
+
+    out = psVectorRecycle(out,nSamples,in->type.type);
+
+    float dX = (endCol - startCol) / (nSamples-1);
+    float dY = (endRow - startRow) / (nSamples-1);
+
+    float x = startCol;
+    float y = startRow;
+
+    #define LINEAR_CUT_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        ps##TYPE* outData = out->data.TYPE; \
+        for (int i = 0; i < nSamples; i++) { \
+            /* store off the location of the sample. */ \
+            if (cutColsData != NULL) { \
+                cutColsData[i] = x; \
+            } \
+            if (cutRowsData != NULL) { \
+                cutRowsData[i] = y; \
+            } \
+            outData[i] = psImagePixelInterpolate(in,x,y,mask,maskVal,0,mode); \
+            x += dX; \
+            y += dY; \
+        } \
+    } \
+    break;
+
+
+    switch (in->type.type) {
+        LINEAR_CUT_CASE(U8);
+        LINEAR_CUT_CASE(U16);
+        LINEAR_CUT_CASE(U32);
+        LINEAR_CUT_CASE(U64);
+        LINEAR_CUT_CASE(S8);
+        LINEAR_CUT_CASE(S16);
+        LINEAR_CUT_CASE(S32);
+        LINEAR_CUT_CASE(S64);
+        LINEAR_CUT_CASE(F32);
+        LINEAR_CUT_CASE(F64);
+        LINEAR_CUT_CASE(C32);
+        LINEAR_CUT_CASE(C64);
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,in->type.type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_TYPE_UNSUPPORTED,
+                       typeStr);
+            psFree(out);
+            out = NULL;
+        }
+    }
+
+    return out;
 }
 
 psVector* psImageRadialCut(psVector* out,
-                           const psImage* input,
+                           const psImage* in,
                            const psImage* restrict mask,
                            unsigned int maskVal,
@@ -633,5 +749,194 @@
                            const psStats* stats)
 {
-
-    return NULL;
+    double statVal;
+
+    /* check the parameters */
+
+    if (in == NULL || in->data.V == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_IMAGE_NULL);
+        psFree(out);
+        return NULL;
+    }
+    int numCols = in->numCols;
+    int numRows = in->numRows;
+
+    if (mask != NULL) {
+        if (numRows != mask->numRows || numCols != mask->numCols) {
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                       PS_ERR_BAD_PARAMETER_VALUE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_SIZE,
+                       mask->numCols,mask->numRows,
+                       numCols, numRows);
+            psFree(out);
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_TYPE,
+                       typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+        }
+    }
+
+    if (centerCol < 0 || centerCol >= numCols ||
+            centerRow < 0 || centerRow >= numRows) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_CENTER_NOT_IN_IMAGE,
+                   centerCol, centerRow,
+                   numCols, numRows);
+        psFree(out);
+    }
+
+    if (radii == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_RADII_VECTOR_NULL);
+        psFree(out);
+        return NULL;
+    }
+
+    if (radii->n < 2) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_RADII_VECTOR_TOOSMALL,
+                   radii->n);
+        psFree(out);
+        return NULL;
+    }
+
+    if (stats == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_STAT_NULL);
+        psFree(out);
+        return NULL;
+    }
+
+    // verify that the stats struct specifies a
+    // single stats operation
+    if (p_psGetStatValue(stats, &statVal) == false) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, false,
+                   PS_ERRORTEXT_psImage_BAD_STAT);
+        psFree(out);
+        return NULL;
+    }
+
+    /* completed checking the parameters */
+
+    // size the output vector to proper size.
+    int numOut = radii->n - 1;
+    out = psVectorRecycle(out, numOut, PS_TYPE_F64);
+    psF64* outData = out->data.F64;
+
+    // sort the radii by value
+    psVector* rSqVec = psVectorCopy(NULL, radii, PS_TYPE_F32);
+    psVectorSort(rSqVec,rSqVec);
+    psF32* rSq = rSqVec->data.F32;
+
+    int startRow = centerRow - rSq[numOut];
+    int endRow = centerRow + rSq[numOut];
+    int startCol = centerCol - rSq[numOut];
+    int endCol = centerCol + rSq[numOut];
+
+    if (startRow < 0) {
+        startRow = 0;
+    }
+
+    if (startCol < 0) {
+        startCol = 0;
+    }
+
+    if (endRow >= numRows) {
+        endRow = numRows - 1;
+    }
+
+    if (endCol >= numCols) {
+        endCol = numCols - 1;
+    }
+
+    // Square the data
+    for (int d = 0; d <= numOut; d++) {
+        rSq[d] *= rSq[d];
+    }
+
+    // create temporary vectors for the data binning step
+    psVector** buffer = psAlloc(sizeof(psVector*)*numOut);
+    psVector** bufferMask = psAlloc(sizeof(psVector*)*numOut);
+    for (int lcv = 0; lcv < numOut; lcv++) {
+        // n.b. alloc enough for the data by making the vectors slightly larger
+        // than the area of the region of interest.
+        buffer[lcv] = psVectorAlloc(1+4*(rSq[lcv+1]-rSq[lcv]),
+                                    in->type.type);
+        buffer[lcv]->n = 0;
+
+        bufferMask[lcv] = NULL;
+        if (mask != NULL) {
+            bufferMask[lcv] = psVectorAlloc(1+4*(rSq[lcv+1]-rSq[lcv]),
+                                            PS_TYPE_MASK);
+            bufferMask[lcv]->n = 0;
+        }
+    }
+
+    float dX;
+    float dY;
+    float dist;
+    for (int row=startRow; row <= endRow; row++) {
+        psF32* inRow = in->data.F32[row];
+        psMaskType* maskRow = NULL;
+        if (mask != NULL) {
+            maskRow = mask->data.PS_TYPE_MASK_DATA[row];
+        }
+        for (int col=startCol; col <= endCol; col++) {
+            dX = centerCol - (float)col - 0.5f;
+            dY = centerRow - (float)row - 0.5f;
+            dist = dX*dX+dY*dY;
+            for (int r = 0; r < numOut;) {
+                if (rSq[r] < dist && dist < rSq[++r]) {
+                    int n = buffer[r]->n;
+                    if (n == buffer[r]->nalloc) { // in case buffers already full, expand
+                        buffer[r] = psVectorRealloc(n*2, buffer[r]);
+                        if (bufferMask[r] != NULL) {
+                            bufferMask[r] = psVectorRealloc(n*2, bufferMask[r]);
+                        }
+                    }
+
+                    buffer[r]->data.F32[n] = inRow[col];
+                    buffer[r]->n = n+1;
+
+                    if (maskRow != NULL) {
+                        bufferMask[r]->data.PS_TYPE_MASK_DATA[n] = maskRow[col];
+                        bufferMask[r]->n = n+1;
+                    }
+
+                    break;
+                }
+            }
+        }
+    }
+
+    psStats* myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+    for (int r = 0; r < numOut; r++) {
+        myStats = psVectorStats(myStats,buffer[r], bufferMask[r],maskVal);
+        (void)p_psGetStatValue(myStats,&statVal);
+        outData[r] = statVal;
+    }
+
+    psFree(myStats);
+
+    for (int lcv = 0; lcv < numOut; lcv++) {
+        psFree(buffer[lcv]);
+        psFree(bufferMask[lcv]);
+    }
+    psFree(buffer);
+    psFree(bufferMask);
+
+    return out;
 }
Index: /trunk/psLib/src/image/psImageExtraction.h
===================================================================
--- /trunk/psLib/src/image/psImageExtraction.h	(revision 1896)
+++ /trunk/psLib/src/image/psImageExtraction.h	(revision 1897)
@@ -10,6 +10,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-09-23 18:31:49 $
+*  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-09-25 02:06:12 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -145,5 +145,6 @@
 psVector* psImageCut(
     psVector* out,                     ///< psVector to recycle, or NULL.
-    psVector* coords,                  ///< if not NULL, the calculated coordinates along the slice (output)
+    psVector* cutCols,                 ///< if not NULL, the calculated column values along the slice (output)
+    psVector* cutRows,                 ///< if not NULL, the calculated row values along the slice (output)
     const psImage* input,              ///< the input image in which to perform the cut
     const psImage* restrict mask,      ///< the mask for the input image.
Index: /trunk/psLib/src/image/psImageManip.c
===================================================================
--- /trunk/psLib/src/image/psImageManip.c	(revision 1896)
+++ /trunk/psLib/src/image/psImageManip.c	(revision 1897)
@@ -10,6 +10,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-25 00:47:54 $
+ *  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -580,5 +580,5 @@
             float inRow = (float)row * invScale; \
             for (int col=0;col<outCols;col++) { \
-                rowData[col] = psImagePixelInterpolate(in,inRow,(float)col*invScale,0,mode); \
+                rowData[col] = psImagePixelInterpolate(in,inRow,(float)col*invScale,NULL,0,0,mode); \
             } \
         }  \
@@ -889,5 +889,5 @@
                 outRow = out->data.TYPE[y]; \
                 for (int x = 0; x < outCols; x++) { \
-                    outRow[x] = p_psImagePixelInterpolate##MODE##_##TYPE(in,inX,inY,unexposedValue); \
+                    outRow[x] = p_psImagePixelInterpolate##MODE##_##TYPE(in,inX,inY,NULL,0,unexposedValue); \
                     inX += cosT; \
                     inY -= sinT; \
@@ -1013,5 +1013,5 @@
         for (int col=0;col<outCols;col++) { \
             outRow[col] = p_psImagePixelInterpolate##MODE##_##TYPE( \
-                          in,dx+(float)col,y,unexposedValue); \
+                          in,dx+(float)col,y,NULL,0,unexposedValue); \
         } \
     } \
Index: /trunk/psLib/src/mathtypes/psImage.c
===================================================================
--- /trunk/psLib/src/mathtypes/psImage.c	(revision 1896)
+++ /trunk/psLib/src/mathtypes/psImage.c	(revision 1897)
@@ -10,6 +10,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.45 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-21 23:15:04 $
+ *  @version $Revision: 1.46 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -199,4 +199,6 @@
                               float x,
                               float y,
+                              const psImage* mask,
+                              unsigned int maskVal,
                               psC64 unexposedValue,
                               psImageInterpolateMode mode)
@@ -214,9 +216,19 @@
     switch (mode) {                                                  \
     case PS_INTERPOLATE_FLAT:                                        \
-        return p_psImagePixelInterpolateFLAT_##TYPE(input, x, y,     \
+        return p_psImagePixelInterpolateFLAT_##TYPE(                 \
+                input,                                               \
+                x,                                                   \
+                y,                                                   \
+                mask,                                                \
+                maskVal,                                             \
                 unexposedValue);                                     \
         break;                                                       \
     case PS_INTERPOLATE_BILINEAR:                                    \
-        return p_psImagePixelInterpolateBILINEAR_##TYPE(input,x,y,   \
+        return p_psImagePixelInterpolateBILINEAR_##TYPE(             \
+                input,                                               \
+                x,                                                   \
+                y,                                                   \
+                mask,                                                \
+                maskVal,                                             \
                 unexposedValue);                                     \
         break;                                                       \
@@ -259,4 +271,6 @@
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psF64 unexposedValue) \
 { \
@@ -269,5 +283,7 @@
             (intX > lastX) || \
             (intY < 0) || \
-            (intY > lastY)) { \
+            (intY > lastY) || \
+            ( (mask!=NULL) && \
+              ((mask->data.PS_TYPE_MASK_DATA[intY][intX] & maskVal) != 0) ) ) { \
         return unexposedValue; \
     } \
@@ -280,4 +296,6 @@
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psC64 unexposedValue) \
 { \
@@ -290,5 +308,7 @@
             (intX > lastX) || \
             (intY < 0) || \
-            (intY > lastY)) { \
+            (intY > lastY) || \
+            ( (mask!=NULL) && \
+              ((mask->data.PS_TYPE_MASK_DATA[intY][intX] & maskVal) != 0) ) ) { \
         return unexposedValue; \
     } \
@@ -314,109 +334,186 @@
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psF64 unexposedValue) \
 { \
     double floorX = floor((psF64)(x) - 0.5); \
     double floorY = floor((psF64)(y) - 0.5); \
-    double fracX = x - 0.5 - floorX; \
-    double fracY = y - 0.5 - floorY; \
+    psF64 fracX = x - 0.5 - floorX; \
+    psF64 fracY = y - 0.5 - floorY; \
     int intFloorX = (int) floorX; \
     int intFloorY = (int) floorY; \
     int lastX = input->numCols - 1; \
     int lastY = input->numRows - 1; \
-    double rx = 0.0; \
-    psF64 pixel = 0.0; \
-    ps##TYPE* currentRow; \
-    ps##TYPE* nextRow; \
-    \
-    if ((intFloorX < 0) || \
-            (intFloorX > lastX) || \
-            (intFloorY < 0) || \
-            (intFloorY > lastY)) { \
-        return unexposedValue; \
-    } \
-    \
-    currentRow = input->data.TYPE[intFloorY]; \
-    if (intFloorY == lastY) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorX < lastX) { \
-            pixel+= fracY * ((psF64)currentRow[intFloorX+1] - \
-                             (psF64)currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    nextRow = input->data.TYPE[intFloorY+1]; \
-    if (intFloorX == lastX) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorY < lastY) { \
-            pixel+= fracX * ((psF64)nextRow[intFloorX] - \
-                             (psF64)currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    \
-    rx = currentRow[intFloorX] + \
-         fracX * ((psF64)currentRow[intFloorX+1] - \
-                  (psF64)currentRow[intFloorX]); \
-    \
-    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
-                          fracX * ((psF64)nextRow[intFloorX+1] - \
-                                   (psF64)nextRow[intFloorX]) - rx); \
-    \
-    return(pixel); \
-}
+    ps##TYPE V00; \
+    ps##TYPE V01; \
+    ps##TYPE V10; \
+    ps##TYPE V11; \
+    bool valid00 = false; \
+    bool valid01 = false; \
+    bool valid10 = false; \
+    bool valid11 = false; \
+    \
+    if (intFloorY >= 0 && intFloorY <= lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V00 = input->data.TYPE[intFloorY][intFloorX]; \
+            valid00 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V10 = input->data.TYPE[intFloorY][intFloorX+1]; \
+            valid10 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    if (intFloorY >= -1 && intFloorY < lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V01 = input->data.TYPE[intFloorY+1][intFloorX]; \
+            valid01 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V11 = input->data.TYPE[intFloorY+1][intFloorX+1]; \
+            valid11 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    \
+    /* cover likely case of all pixels being valid more efficiently */  \
+    if (valid00 && valid10 && valid01 && valid11) { \
+        /* formula from the ADD */ \
+        psF64 rx = V00 + (V10-V00)*fracX; \
+        return (rx + (V01 + (V11 - V01) * fracX - rx) * fracY); \
+    } \
+    \
+    /* OK, at least one pixel is not valid - need to do it piecemeal */ \
+    \
+    psF64 V0; \
+    bool valid0 = true; \
+    if (valid00 && valid10) { \
+        V0 = V00*(1-fracX)+V10*fracX; \
+    } else if (valid00) { \
+        V0 = V00; \
+    } else if (valid10) { \
+        V0 = V10; \
+    } else { \
+        valid0 = false; \
+    } \
+    \
+    psF64 V1; \
+    bool valid1 = true; \
+    if (valid01 && valid11) { \
+        V0 = V01*(1-fracX)+V11*fracX; \
+    } else if (valid01) { \
+        V0 = V01; \
+    } else if (valid11) { \
+        V0 = V11; \
+    } else { \
+        valid1 = false; \
+    } \
+    \
+    if (valid0 && valid1) { \
+        return ( V0*(1-fracY) + V1*fracY ); \
+    } else if (valid0) { \
+        return V0; \
+    } else if (valid1) { \
+        return V1; \
+    } \
+    \
+    return unexposedValue; \
+}
+
 #define PSIMAGE_PIXEL_INTERPOLATE_BILINEAR_COMPLEX(TYPE) \
 inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE(const psImage* input, \
         float x, \
         float y, \
+        const psImage* mask, \
+        unsigned int maskVal, \
         psC64 unexposedValue) \
 { \
     double floorX = floor((psF64)(x) - 0.5); \
     double floorY = floor((psF64)(y) - 0.5); \
-    double fracX = x - 0.5 - floorX; \
-    double fracY = y - 0.5 - floorY; \
+    psF64 fracX = x - 0.5 - floorX; \
+    psF64 fracY = y - 0.5 - floorY; \
     int intFloorX = (int) floorX; \
     int intFloorY = (int) floorY; \
     int lastX = input->numCols - 1; \
     int lastY = input->numRows - 1; \
-    double rx = 0.0; \
-    psC64 pixel = 0.0; \
-    ps##TYPE* currentRow; \
-    ps##TYPE* nextRow; \
-    \
-    if ((intFloorX < 0) || \
-            (intFloorX > lastX) || \
-            (intFloorY < 0) || \
-            (intFloorY > lastY)) { \
-        return unexposedValue; \
-    } \
-    \
-    currentRow = input->data.TYPE[intFloorY]; \
-    if (intFloorY == lastY) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorX < lastX) { \
-            pixel+= fracY * (currentRow[intFloorX+1] - \
-                             currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    nextRow = input->data.TYPE[intFloorY+1]; \
-    if (intFloorX == lastX) { \
-        pixel = currentRow[intFloorX]; \
-        if (intFloorY < lastY) { \
-            pixel+= fracX * (nextRow[intFloorX] - \
-                             currentRow[intFloorX]); \
-        } \
-        return(pixel); \
-    } \
-    \
-    rx = currentRow[intFloorX] + \
-         fracX * (currentRow[intFloorX+1] - \
-                  currentRow[intFloorX]); \
-    \
-    pixel = rx + fracY * ((psF64)nextRow[intFloorX] + \
-                          fracX * (nextRow[intFloorX+1] - \
-                                   nextRow[intFloorX]) - rx); \
-    \
-    return(pixel); \
+    ps##TYPE V00; \
+    ps##TYPE V01; \
+    ps##TYPE V10; \
+    ps##TYPE V11; \
+    bool valid00 = false; \
+    bool valid01 = false; \
+    bool valid10 = false; \
+    bool valid11 = false; \
+    \
+    if (intFloorY >= 0 && intFloorY <= lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V00 = input->data.TYPE[intFloorY][intFloorX]; \
+            valid00 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V10 = input->data.TYPE[intFloorY][intFloorX+1]; \
+            valid10 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    if (intFloorY >= -1 && intFloorY < lastY) { \
+        if (intFloorX >= 0 && intFloorX <= lastX) { \
+            V01 = input->data.TYPE[intFloorY+1][intFloorX]; \
+            valid01 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX] & maskVal) == 0); \
+        } \
+        if (intFloorX >= -1 && intFloorX < lastX) { \
+            V11 = input->data.TYPE[intFloorY+1][intFloorX+1]; \
+            valid11 = (mask == NULL) || \
+                      ((mask->data.PS_TYPE_MASK_DATA[intFloorY+1][intFloorX+1] & maskVal) == 0); \
+        } \
+    } \
+    \
+    /* cover likely case of all pixels being valid */  \
+    if (valid00 && valid10 && valid01 && valid11) { \
+        /* formula from the ADD */ \
+        psC64 rx = V00 + (V10-V00)*fracX; \
+        return (rx + (V01 + (V11 - V01) * fracX - rx) * fracY); \
+    } \
+    \
+    /* OK, at least one pixel is not valid - need to do it piecemeal */ \
+    \
+    psC64 V0; \
+    bool valid0 = true; \
+    if (valid00 && valid10) { \
+        V0 = V00*(1-fracX)+V10*fracX; \
+    } else if (valid00) { \
+        V0 = V00; \
+    } else if (valid10) { \
+        V0 = V10; \
+    } else { \
+        valid0 = false; \
+    } \
+    \
+    psC64 V1; \
+    bool valid1 = true; \
+    if (valid01 && valid11) { \
+        V0 = V01*(1-fracX)+V11*fracX; \
+    } else if (valid01) { \
+        V0 = V01; \
+    } else if (valid11) { \
+        V0 = V11; \
+    } else { \
+        valid1 = false; \
+    } \
+    \
+    if (valid0 && valid1) { \
+        return ( V0*(1-fracY) + V1*fracY ); \
+    } else if (valid0) { \
+        return V0; \
+    } else if (valid1) { \
+        return V1; \
+    } \
+    \
+    return unexposedValue; \
 }
 
Index: /trunk/psLib/src/mathtypes/psImage.h
===================================================================
--- /trunk/psLib/src/mathtypes/psImage.h	(revision 1896)
+++ /trunk/psLib/src/mathtypes/psImage.h	(revision 1897)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-21 19:51:41 $
+ *  @version $Revision: 1.37 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -118,4 +118,6 @@
     float x,                           ///< column location to derive value of
     float y,                           ///< row location ot derive value of
+    const psImage* mask,               ///< if not NULL, the mask of the input image
+    unsigned int maskVal,              ///< the mask value
     psC64 unexposedValue,              ///< return value if x,y location is not in image.
     psImageInterpolateMode mode        ///< interpolation mode
@@ -124,28 +126,36 @@
 #define p_psImagePixelInterpolateFcns(TYPE) \
 inline psF64 p_psImagePixelInterpolateFLAT_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psF64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psF64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                  ); \
 inline psF64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psF64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psF64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                      );
 
 #define p_psImagePixelInterpolateComplexFcns(TYPE) \
 inline psC64 p_psImagePixelInterpolateFLAT_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psC64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psC64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                  ); \
 inline psC64 p_psImagePixelInterpolateBILINEAR_##TYPE( \
-        const psImage* input, \
-        float x, \
-        float y, \
-        psC64 unexposedValue \
+        const psImage* input,          /**< input image for interpolation */ \
+        float x,                       /**< column location to derive value of */ \
+        float y,                       /**< row location ot derive value of */ \
+        const psImage* mask,           /**< if not NULL, the mask of the input image */ \
+        unsigned int maskVal,          /**< the mask value */ \
+        psC64 unexposedValue           /**< return value if x,y location is not in image. */ \
                                                      );
 
@@ -162,4 +172,6 @@
 p_psImagePixelInterpolateComplexFcns(C32)
 p_psImagePixelInterpolateComplexFcns(C64)
+
 /// @}
+
 #endif
Index: /trunk/psLib/src/mathtypes/psVector.c
===================================================================
--- /trunk/psLib/src/mathtypes/psVector.c	(revision 1896)
+++ /trunk/psLib/src/mathtypes/psVector.c	(revision 1897)
@@ -10,6 +10,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-09-16 23:47:43 $
+*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-09-25 02:06:12 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -110,4 +110,108 @@
 }
 
+psVector* psVectorCopy(psVector* out, const psVector* in, psElemType type)
+{
+    if (in == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psVectorSort",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psVector_SORT_NULL);
+        psFree(out);
+        return NULL;
+    }
+
+    int nElements = in->n;
+
+    out = psVectorRecycle(out, nElements, type);
+
+    #define PSVECTOR_COPY(INTYPE,OUTTYPE) { \
+        ps##INTYPE *inVec = in->data.INTYPE; \
+        ps##OUTTYPE *outVec = out->data.OUTTYPE; \
+        for (int col=0;col<nElements;col++) { \
+            *(outVec++) = *(inVec++); \
+        } \
+    }
+
+    #define PSVECTOR_COPY_CASE(OUTTYPE) \
+case PS_TYPE_##OUTTYPE: { \
+        switch (in->type.type) { \
+        case PS_TYPE_S8: \
+            PSVECTOR_COPY(S8,OUTTYPE); \
+            break; \
+        case PS_TYPE_S16: \
+            PSVECTOR_COPY(S16,OUTTYPE); \
+            break; \
+        case PS_TYPE_S32: \
+            PSVECTOR_COPY(S32,OUTTYPE); \
+            break; \
+        case PS_TYPE_S64: \
+            PSVECTOR_COPY(S64,OUTTYPE); \
+            break; \
+        case PS_TYPE_U8: \
+            PSVECTOR_COPY(U8,OUTTYPE); \
+            break; \
+        case PS_TYPE_U16: \
+            PSVECTOR_COPY(U16,OUTTYPE); \
+            break; \
+        case PS_TYPE_U32: \
+            PSVECTOR_COPY(U32,OUTTYPE); \
+            break; \
+        case PS_TYPE_U64: \
+            PSVECTOR_COPY(U64,OUTTYPE); \
+            break; \
+        case PS_TYPE_F32: \
+            PSVECTOR_COPY(F32,OUTTYPE); \
+            break; \
+        case PS_TYPE_F64: \
+            PSVECTOR_COPY(F64,OUTTYPE); \
+            break; \
+        case PS_TYPE_C32: \
+            PSVECTOR_COPY(C32,OUTTYPE); \
+            break; \
+        case PS_TYPE_C64: \
+            PSVECTOR_COPY(C64,OUTTYPE); \
+            break; \
+        default: { \
+                char* typeStr; \
+                PS_TYPE_NAME(typeStr,type); \
+                psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCopy", \
+                           PS_ERR_BAD_PARAMETER_TYPE, true, \
+                           PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE, \
+                           typeStr); \
+                psFree(out); \
+            } \
+        } \
+        break; \
+    }
+
+    switch (type) {
+        PSVECTOR_COPY_CASE(S8);
+        PSVECTOR_COPY_CASE(S16);
+        PSVECTOR_COPY_CASE(S32);
+        PSVECTOR_COPY_CASE(S64);
+        PSVECTOR_COPY_CASE(U8);
+        PSVECTOR_COPY_CASE(U16);
+        PSVECTOR_COPY_CASE(U32);
+        PSVECTOR_COPY_CASE(U64);
+        PSVECTOR_COPY_CASE(F32);
+        PSVECTOR_COPY_CASE(F64);
+        PSVECTOR_COPY_CASE(C32);
+        PSVECTOR_COPY_CASE(C64);
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCopy",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE,
+                       typeStr);
+            psFree(out);
+
+            break;
+        }
+    }
+    return out;
+
+
+}
+
 psVector* psVectorSort(psVector* restrict outVector, const psVector* restrict inVector)
 {
Index: /trunk/psLib/src/mathtypes/psVector.h
===================================================================
--- /trunk/psLib/src/mathtypes/psVector.h	(revision 1896)
+++ /trunk/psLib/src/mathtypes/psVector.h	(revision 1897)
@@ -12,6 +12,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-08-11 20:17:35 $
+ *  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-25 02:06:12 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -105,4 +105,18 @@
 );
 
+/** Copy a vector, converting types.
+ *
+ *  Performs a deep copy of the elements of one psVector to a new psVector, 
+ *  converting numeric types to a specified type.
+ *
+ * @return psVector*       Pointer to resulting psVector.
+ *
+ */
+psVector* psVectorCopy(
+    psVector* out,                     ///< if non-NULL, a psVector to recycle
+    const psVector* in,                ///< the vector to copy.
+    psElemType type                    ///< the data type of the resulting psVector
+);
+
 /** Sort an array of floats.
  *
