Index: trunk/psLib/src/imageops/psImageConvolve.c
===================================================================
--- trunk/psLib/src/imageops/psImageConvolve.c	(revision 17365)
+++ trunk/psLib/src/imageops/psImageConvolve.c	(revision 17726)
@@ -7,6 +7,6 @@
 /// @author Eugene Magnier, IfA
 ///
-/// @version $Revision: 1.66 $ $Name: not supported by cvs2svn $
-/// @date $Date: 2008-04-07 20:30:38 $
+/// @version $Revision: 1.67 $ $Name: not supported by cvs2svn $
+/// @date $Date: 2008-05-17 01:38:20 $
 ///
 /// Copyright 2004-2007 Institute for Astronomy, University of Hawaii
@@ -755,2 +755,105 @@
     return true;
 }
+
+
+
+
+psImage *psImageConvolveMask(psImage *out, const psImage *mask, psMaskType maskVal,
+                             psMaskType setVal, int xMin, int xMax, int yMin, int yMax)
+{
+    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
+    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL);
+    if (out) {
+        PS_ASSERT_IMAGE_NON_NULL(out, NULL);
+        PS_ASSERT_IMAGE_TYPE(out, PS_TYPE_MASK, NULL);
+        PS_ASSERT_IMAGES_SIZE_EQUAL(out, mask, NULL);
+        if (out == mask && ((maskVal & setVal) || !setVal)) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Can't convolve mask in-place if values to set contains values to convolve.");
+            return NULL;
+        }
+    }
+
+    if (yMin > yMax) {
+        psWarning("Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
+                 yMin, yMax);
+
+        int temp = yMin;
+        yMin = yMax;
+        yMax = temp;
+    }
+    if (xMin > xMax) {
+        psWarning("Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
+                 xMin, xMax);
+
+        int temp = xMin;
+        xMin = xMax;
+        xMax = temp;
+    }
+
+    int numRows = mask->numRows;        // Number of rows
+    int numCols = mask->numCols;        // Number of columns
+
+    if (!out) {
+        // Propagate the non-masked values
+        out = (psImage*)psBinaryOp(NULL, (const psPtr)mask, "&", psScalarAlloc(~maskVal, PS_TYPE_MASK));
+    }
+
+    if (!setVal) {
+        setVal = maskVal;
+    }
+
+    // Dereference mask images
+    psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA;
+    psMaskType **outData = out->data.PS_TYPE_MASK_DATA;
+
+    // Since we're just masking everything inside a square, it's separable
+    for (int y = 0; y < numRows; y++) {
+        int min = 0, max = 0;           // Minimum and maximum points to mask
+        bool masking = false;           // Currently masking?
+        for (int x = 0; x < numCols; x++) {
+            if (maskData[y][x] & maskVal) {
+                if (!masking) {
+                    masking = true;
+                    min = x + xMin;
+                    max = x + xMax;
+                } else {
+                    max++;
+                }
+            } else if (masking) {
+                // Do the masking
+                masking = false;
+                min = PS_MAX(0, min);
+                max = PS_MIN(numCols - 1, max);
+                for (int i = min; i < max; i++) {
+                    outData[y][i] |= setVal;
+                }
+            }
+        }
+    }
+    for (int x = 0; x < numCols; x++) {
+        int min = 0, max = 0;           // Minimum and maximum points to mask
+        bool masking = false;           // Currently masking?
+        for (int y = 0; y < numRows; y++) {
+            if (maskData[y][x] & maskVal) {
+                if (!masking) {
+                    masking = true;
+                    min = y + yMin;
+                    max = y + yMax;
+                } else {
+                    max++;
+                }
+            } else if (masking) {
+                // Do the masking
+                masking = false;
+                min = PS_MAX(0, min);
+                max = PS_MIN(numRows - 1, max);
+                for (int i = min; i < max; i++) {
+                    outData[i][x] |= setVal;
+                }
+            }
+        }
+    }
+
+    return out;
+}
