Index: trunk/psLib/src/image/psImage.c
===================================================================
--- trunk/psLib/src/image/psImage.c	(revision 1841)
+++ 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; \
 }
 
