Index: /trunk/psLib/src/imageops/psImageMaskOps.c
===================================================================
--- /trunk/psLib/src/imageops/psImageMaskOps.c	(revision 5256)
+++ /trunk/psLib/src/imageops/psImageMaskOps.c	(revision 5256)
@@ -0,0 +1,306 @@
+/** @file  psImageMaskOps.c
+ *
+ *  @brief Contains basic image pixel and geometry manipulation operations, as
+ *         specified in the PSLIB SDRS sections "Mask Operations"
+ *
+ *  @ingroup Image
+ *
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-10-10 20:12:13 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <complex.h>
+#include <math.h>                          // for isfinite(), etc.
+#include <stdlib.h>
+#include <string.h>                        // for memcpy, etc.
+
+#include "psImageMaskOps.h"
+
+#include "psError.h"
+#include "psImage.h"
+#include "psStats.h"
+#include "psMemory.h"
+#include "psConstants.h"
+#include "psErrorText.h"
+#include "psCoord.h"
+
+// mask the area contained by the region
+// the region is defined wrt the parent image
+void psImageMaskRegion(psImage *image,
+                       psRegion region,
+                       const char *op,
+                       psMaskType maskValue)
+{
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+    for (int j = 0; j < image->numRows; j++) {
+        for (int i = 0; i < image->numCols; i++) {
+            if ( (j + image->row0) >= region.y0 &&
+                    (j + image->row0) <= region.y1 &&
+                    (i + image->col0) >= region.x0 &&
+                    (i + image->col0) <= region.x1 ) {
+                if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] &= maskValue;
+                } else if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] |= maskValue;
+                } else if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] = maskValue;
+                } else if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] ^= maskValue;
+                } else {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+                            "The logical operation specified is incorrect\n");
+                    return;
+                }
+            }
+        }
+    }
+    /*
+        for (int iy = 0; iy < image->numRows; iy++) {
+            for (int ix = 0; ix < image->numCols; ix++) {
+                if (ix + image->col0 >=  region.x0)
+                    continue;
+                if (ix + image->col0 <= region.x1)
+                    continue;
+                if (iy + image->row0 >=  region.y0)
+                    continue;
+                if (iy + image->row0 <= region.y1)
+                    continue;
+                if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] &= maskValue;
+                } else if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] |= maskValue;
+                } else if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] = maskValue;
+                } else if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] ^= maskValue;
+                }
+            }
+        }
+    */
+}
+
+// mask the area not contained by the region
+// the region is defined wrt the parent image
+void psImageKeepRegion(psImage *image,
+                       psRegion region,
+                       const char *op,
+                       psMaskType maskValue)
+{
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+    for (int j = 0; j < image->numRows; j++) {
+        for (int i = 0; i < image->numCols; i++) {
+            if ( (j + image->row0) < region.y0 ||
+                    (j + image->row0) > region.y1 ||
+                    (i + image->col0) < region.x0 ||
+                    (i + image->col0) > region.x1 ) {
+                if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] &= maskValue;
+                } else if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] |= maskValue;
+                } else if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] = maskValue;
+                } else if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[j][i] ^= maskValue;
+                } else {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+                            "The logical operation specified is incorrect\n");
+                    return;
+                }
+            }
+        }
+    }
+    /*
+        for (int iy = 0; iy < image->numRows; iy++) {
+            for (int ix = 0; ix < image->numCols; ix++) {
+                if (ix + image->col0 <  region.x0)
+                    goto maskit;
+                if (ix + image->col0 > region.x1)
+                    goto maskit;
+                if (iy + image->row0 <  region.y0)
+                    goto maskit;
+                if (iy + image->row0 > region.y1)
+                    goto maskit;
+                continue;
+    maskit:
+                if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] &= maskValue;
+                } else if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] |= maskValue;
+                } else if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] = maskValue;
+                } else if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] ^= maskValue;
+                }
+            }Robert DeSonia, MHPCC
+    *  @author Ross Harman, MHPCC
+        }
+    */
+}
+
+// mask the area contained by the region
+// the region is defined wrt the parent image
+void psImageMaskCircle(psImage *image,
+                       double x,
+                       double y,
+                       double radius,
+                       const char *op,
+                       psMaskType maskValue)
+{
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+
+
+    double dx, dy, r2, R2;
+
+    R2 = PS_SQR(radius);
+
+    for (int iy = 0; iy < image->numRows; iy++) {
+        for (int ix = 0; ix < image->numCols; ix++) {
+            dx = ix + image->col0 - x;
+            dy = iy + image->row0 - y;
+            r2 = PS_SQR(dx) + PS_SQR(dy);
+            if (r2 <= R2) {
+                if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] &= maskValue;
+                } else if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] |= maskValue;
+                } else if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] = maskValue;
+                } else if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] ^= maskValue;
+                } else {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+                            "The logical operation specified is incorrect\n");
+                    return;
+                }
+            }
+        }
+    }
+}
+
+// mask the area contained by the region
+// the region is defined wrt the parent image
+void psImageKeepCircle(psImage *image,
+                       double x,
+                       double y,
+                       double radius,
+                       const char *op,
+                       psMaskType maskValue)
+{
+
+    if (image == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid image input.  Image is NULL.\n");
+        return;
+    }
+    double dx, dy, r2, R2;
+
+    R2 = PS_SQR(radius);
+
+    for (int iy = 0; iy < image->numRows; iy++) {
+        for (int ix = 0; ix < image->numCols; ix++) {
+            dx = ix + image->col0 - x;
+            dy = iy + image->row0 - y;
+            r2 = PS_SQR(dx) + PS_SQR(dy);
+            if (r2 > R2) {
+                if ( !strncmp(op, "&", 2) || !strncmp(op, "AND", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] &= maskValue;
+                } else if ( !strncmp(op, "|", 2) || !strncmp(op, "OR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] |= maskValue;
+                } else if ( !strncmp(op, "=", 2) || !strncmp(op, "EQUAL", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] = maskValue;
+                } else if ( !strncmp(op, "^", 2) || !strncmp(op, "XOR", 5) ) {
+                    image->data.PS_TYPE_MASK_DATA[iy][ix] ^= maskValue;
+                } else {
+                    psError(PS_ERR_BAD_PARAMETER_VALUE,true,
+                            "The logical operation specified is incorrect\n");
+                    return;
+                }
+            }
+        }
+    }
+}
+
+psImage *psImageGrowMask(psImage *out,
+                         const psImage *in,
+                         psMaskType maskVal,
+                         unsigned int growSize,
+                         psMaskType growVal)
+{
+    if (in == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                "Invalid input image.  Input image cannot be NULL.\n");
+        return NULL;
+    }
+    if (in->type.type != PS_TYPE_MASK) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                "Invalid input image.  Input image type must match psMaskType.\n");
+        return NULL;
+    }
+    if (out != NULL) {
+        if (out->numCols != in->numCols || out->numRows != in->numRows) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid out image.  Size of out does not match size of in.\n");
+            return NULL;
+        }
+        if (out->type.type != in->type.type) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid out image.  Type of out does not match type of in.\n");
+            return NULL;
+        }
+    }
+    if (out == NULL) {
+        out = psImageAlloc(in->numCols, in->numRows, in->type.type);
+    }
+    psImage *changed = psImageAlloc(in->numCols, in->numRows, in->type.type);
+    int k,l,m,n;
+    for (k = 0; k < in->numRows; k++) {
+        for (l = 0; l < in->numCols; l++) {
+            out->data.PS_TYPE_MASK_DATA[k][l] = in->data.PS_TYPE_MASK_DATA[k][l];
+            changed->data.PS_TYPE_MASK_DATA[k][l] = 0;
+        }
+    }
+    for (int i = 0; i < in->numRows; i++) {
+        for (int j = 0; j < in->numCols; j++) {
+            if ( (in->data.PS_TYPE_MASK_DATA[i][j] & maskVal) != 0 &&
+                    changed->data.PS_TYPE_MASK_DATA[i][j] == 0) {
+                m = i - growSize;
+                if (m < 0) {
+                    m = 0;
+                }
+                for (k = m; k <= (i + growSize) && k < in->numRows; k++) {
+                    n = j - growSize;
+                    if (n < 0) {
+                        n = 0;
+                    }
+                    for (l = n; l <= (j + growSize) && l < in->numCols; l++) {
+                        if (((k-i)*(k-i) + (l-j)*(l-j)) <= (growSize*growSize)) {
+                            out->data.PS_TYPE_MASK_DATA[k][l] |= growVal;
+                            if ( (in->data.PS_TYPE_MASK_DATA[i][j] & maskVal) == 0 ) {
+                                changed->data.PS_TYPE_MASK_DATA[k][l] = 1;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    psFree(changed);
+    return out;
+}
+
Index: /trunk/psLib/src/imageops/psImageMaskOps.h
===================================================================
--- /trunk/psLib/src/imageops/psImageMaskOps.h	(revision 5256)
+++ /trunk/psLib/src/imageops/psImageMaskOps.h	(revision 5256)
@@ -0,0 +1,97 @@
+/** @file  psImageMaskOps.h
+ *
+ *  @brief Contains basic image pixel manipulation operations, as
+ *         specified in the PSLIB SDRS sections "Mask Operations"
+ *
+ *  @ingroup Image
+ *
+ *  @author David Robbins, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-10-10 20:12:13 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_IMAGE_MASK_OPS_H
+#define PS_IMAGE_MASK_OPS_H
+
+#include "psImage.h"
+#include "psCoord.h"
+#include "psStats.h"
+#include "psPixels.h"
+
+/// @addtogroup Image
+/// @{
+
+/** Sets the bits inside the region, ignoring pixels outside.
+ *
+ *  The pixels are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageMaskRegion(
+    psImage *image,                    ///< the image to set
+    psRegion region,                   ///< the specified region
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Sets the bits outside the region, ignoring pixels inside.
+ *
+ *  The pixels are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageKeepRegion(
+    psImage *image,                    ///< the image to set
+    psRegion region,                   ///< the specified region
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Sets the bits inside the circle, ignoring the pixels outside.
+ *
+ *  The pixel values are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageMaskCircle(
+    psImage *image,                    ///< the image to set
+    double x,                          ///< the x coordinate of the circle's center
+    double y,                          ///< the y coordinate of the circle's center
+    double radius,                     ///< the radius of the specified circle
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Sets the bits outside the circle, ignoring the pixels inside.
+ *
+ *  The pixel values are set by combining the existing pixel value and the given maskValue
+ *  with a logical operation.  The allowed operations are =, AND, OR, and XOR.
+ */
+void psImageKeepCircle(
+    psImage *image,                    ///< the image to set
+    double x,                          ///< the x coordinate of the circle's center
+    double y,                          ///< the y coordinate of the circle's center
+    double radius,                     ///< the radius of the specified circle
+    const char *op,                    ///< the logical operation
+    psMaskType maskValue               ///< the specified bits
+);
+
+/** Grows the specified values on the imput mask image, in, returning the result.
+ *
+ *  If out is NULL, then a new image of the same type and dimension as in shall
+ *  be allocated and returned; otherwise out shall be modified.  If out is non-
+ *  NULL and does not have the same size and type as in, the function shall
+ *  generate an error and return NULL.  Pixels in the in image within growSize
+ *  pixels (either horizontal or vertical) of a pixel which matches the maskVal
+ *  shall have the corresponding pixel in the out image set to the growVal.
+ *
+ *  @return psImage*:
+ */
+psImage *psImageGrowMask(
+    psImage *out,                      ///< the image to set and return
+    const psImage *in,                 ///< the input to image
+    psMaskType maskVal,                ///< the specified mask value
+    unsigned int growSize,             ///< the range of values from maskVal
+    psMaskType growVal                 ///< the output value to set
+);
+
+#endif // #ifndef PS_MASK_OPS_H
