Index: trunk/psLib/src/imageops/psImageStats.c
===================================================================
--- trunk/psLib/src/imageops/psImageStats.c	(revision 6346)
+++ trunk/psLib/src/imageops/psImageStats.c	(revision 6750)
@@ -9,6 +9,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.90 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-02-07 23:14:21 $
+ *  @version $Revision: 1.91 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-04-01 02:43:57 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -267,6 +267,8 @@
     // We scale the pixel positions to values
     // between -1.0 and 1.0
-    rScalingFactors = calcScaleFactors(input->numRows);
-    cScalingFactors = calcScaleFactors(input->numCols);
+    //    rScalingFactors = calcScaleFactors(input->numRows);
+    //    cScalingFactors = calcScaleFactors(input->numCols);
+    rScalingFactors = calcScaleFactors(input->row0 + input->numRows);
+    cScalingFactors = calcScaleFactors(input->col0 + input->numCols);
 
     // Determine how many Chebyshev polynomials
@@ -283,6 +285,8 @@
         for (j = 0; j < (1 + coeffs->nY); j++) {
             sums[i][j] = 0.0;
-            for (x = 0; x < input->numRows; x++) {
-                for (y = 0; y < input->numCols; y++) {
+            //            for (x = 0; x < input->numRows; x++) {
+            //                for (y = 0; y < input->numCols; y++) {
+            for (x = input->row0; x < (input->row0 + input->numRows); x++) {
+                for (y = input->col0; y < (input->col0 + input->numCols); y++) {
                     double pixel = 0.0;
                     if (input->type.type == PS_TYPE_S8) {
@@ -399,5 +403,6 @@
             //            nodes->data.F64[x][y] = psImagePixelInterpolate(input, yNode, xNode, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
             //            nodes->data.F64[x][y] = psImagePixelInterpolate(input, yTmp, xTmp, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
-            nodes->data.F64[x][y] = psImagePixelInterpolate(input, yOrig, xOrig, NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+            nodes->data.F64[x][y] = psImagePixelInterpolate(input, yOrig, xOrig, NULL,
+                                    0, 0.0, PS_INTERPOLATE_BILINEAR);
         }
     }
@@ -505,6 +510,8 @@
     // We scale the pixel positions to values between -1.0 and 1.0
     // Use static data structures here.
-    rScalingFactors = calcScaleFactors(input->numRows);
-    cScalingFactors = calcScaleFactors(input->numCols);
+    //    rScalingFactors = calcScaleFactors(input->numRows);
+    //    cScalingFactors = calcScaleFactors(input->numCols);
+    rScalingFactors = calcScaleFactors(input->numRows+input->row0);
+    cScalingFactors = calcScaleFactors(input->numCols+input->col0);
 
     // Determine how many Chebyshev polynomials
@@ -517,6 +524,8 @@
     chebPolys = p_psCreateChebyshevPolys(maxChebyPoly + 1);
 
-    for (x = 0; x < input->numRows; x++) {
-        for (y = 0; y < input->numCols; y++) {
+    //    for (x = 0; x < input->numRows; x++) {
+    //        for (y = 0; y < input->numCols; y++) {
+    for (x = input->row0; x < (input->row0 + input->numRows); x++) {
+        for (y = input->col0; y < (input->col0 + input->numCols); y++) {
             polySum = 0.0;
             for (i = 0; i < (1 + coeffs->nX); i++) {
@@ -563,11 +572,15 @@
         for (int col = 0; col < input->numCols ; col++) {
             if (input->type.type == PS_TYPE_S8) {
-                input->data.S8[row][col] = (psS8) psPolynomial2DEval(coeffs, (psF32) row, (psF32) col);
+                input->data.S8[row][col] = (psS8) psPolynomial2DEval(coeffs,
+                                           (psF32) (row + input->row0), (psF32) (col + input->col0));
             } else if (input->type.type == PS_TYPE_U16) {
-                input->data.U16[row][col] = (psS16) psPolynomial2DEval(coeffs, (psF32) row, (psF32) col);
+                input->data.U16[row][col] = (psS16) psPolynomial2DEval(coeffs,
+                                            (psF32) (row + input->row0), (psF32) (col + input->col0));
             } else if (input->type.type == PS_TYPE_F32) {
-                input->data.F32[row][col] = psPolynomial2DEval(coeffs, (psF32) row, (psF32) col);
+                input->data.F32[row][col] = psPolynomial2DEval(coeffs,
+                                            (psF32) (row + input->row0), (psF32) (col + input->col0));
             } else if (input->type.type == PS_TYPE_F64) {
-                input->data.F64[row][col] = (psF64) psPolynomial2DEval(coeffs, (psF32) row, (psF32) col);
+                input->data.F64[row][col] = (psF64) psPolynomial2DEval(coeffs,
+                                            (psF32) (row + input->row0), (psF32) (col + input->col0));
             }
         }
@@ -617,9 +630,4 @@
     int y1 = 0;
     psElemType type;
-    if (mask == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL, true,
-                PS_ERRORTEXT_psImage_IMAGE_NULL);
-        return -1;
-    }
 
     // this is not a valid error: a psRegion with ranges outside the valid pixels
@@ -641,16 +649,117 @@
 
     // rationalize the region
-    region = psRegionForImage(mask, region);
-
-    if (region.x0 == region.x1 || region.y0 == region.y1) {
-        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
-                "psRegion input contains 0 pixels\n");
+
+    /*
+        if (mask == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_NULL, true,
+                    PS_ERRORTEXT_psImage_IMAGE_NULL);
+            return -1;
+        }
+        region = psRegionForImage(mask, region);
+     
+        if (region.x0 == region.x1 || region.y0 == region.y1) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "psRegion input contains 0 pixels\n");
+            return -1;
+        }
+    */
+    PS_ASSERT_IMAGE_NON_NULL(mask, -1);
+    PS_ASSERT_INT_NONNEGATIVE(mask->col0, -1);
+    PS_ASSERT_INT_NONNEGATIVE(mask->row0, -1);
+    PS_ASSERT_INT_POSITIVE(mask->numCols, -1);
+    PS_ASSERT_INT_POSITIVE(mask->numRows, -1);
+
+    /*    x0 = (int)(roundf(region.x0));
+        x1 = (int)(roundf(region.x1));
+        y0 = (int)(roundf(region.y0));
+        y1 = (int)(roundf(region.y1));
+    */
+    int col0 = (int)(roundf(region.x0));
+    int col1 = (int)(roundf(region.x1));
+    int row0 = (int)(roundf(region.y0));
+    int row1 = (int)(roundf(region.y1));
+    //If (0,0,0,0) specified, the whole image is to be used.
+    if (col0 == 0 && col1 == 0 && row0 == 0 && row1 == 0) {
+        col0 = mask->col0;
+        col1 = mask->col0 + mask->numCols - 1;
+        row0 = mask->row0;
+        row1 = mask->row0 + mask->numRows - 1;
+    }
+
+    //Make sure x0 of region is inside image.  If so, set col0 to corresponding index number.
+    if (col0 >= mask->col0 && col0 < (mask->col0 + mask->numCols) ) {
+        col0 -= mask->col0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, x0=%f, is out of range [%d,%d].\n",
+                region.x0, mask->col0, mask->col0+mask->numCols-1);
         return -1;
     }
-
-    x0 = (int)(roundf(region.x0));
-    x1 = (int)(roundf(region.x1));
-    y0 = (int)(roundf(region.y0));
-    y1 = (int)(roundf(region.y1));
+    //Make sure y0 of region is inside image.  If so, set row0 to corresponding index number.
+    if (row0 >= mask->row0 && row0 < (mask->row0 + mask->numRows) ) {
+        row0 -= mask->row0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, y0=%f, is out of range [%d,%d].\n",
+                region.y0, mask->row0, mask->row0+mask->numRows-1);
+        return -1;
+    }
+
+    //Make sure x1 of region is valid.  If negative, index from tail (if valid).
+    if (col1 < 0) {
+        col1 += mask->numCols;
+        if (col1 < 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified psRegion parameter, x1=%f=%d, is out of range [%d,%d].\n",
+                    region.x1, col1+mask->col0, mask->col0, mask->col0+mask->numCols-1);
+            return -1;
+        }
+    } else if (col1 >= mask->col0 && col1 < (mask->col0 + mask->numCols) ) {
+        col1 -= mask->col0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, x1=%f=%d, is out of range [%d,%d].\n",
+                region.x1, col1, mask->col0, mask->col0+mask->numCols-1);
+        return -1;
+    }
+    //Make sure y1 of region is valid.  If negative, index from tail (if valid).
+    if (row1 < 0) {
+        row1 += mask->numRows;
+        if (row1 < 0) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Specified psRegion parameter, y1=%f=%d, is out of range [%d,%d].\n",
+                    region.y1, row1+mask->row0, mask->row0, mask->row0+mask->numRows-1);
+            return -1;
+        }
+    } else if (row1 >= mask->row0 && row1 < (mask->row0 + mask->numRows) ) {
+        row1 -= mask->row0;
+    } else {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                "Specified psRegion parameter, y1=%f=%d, is out of range [%d,%d].\n",
+                region.y1, row1, mask->row0, mask->row0+mask->numRows-1);
+        return -1;
+    }
+    //Now make sure that the region makes sense.
+    if (col0 > col1 || row0 > row1) {
+        if (col0 > col1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid psRegion specified.  x0=%f=%d is greater than x1=%f=%d.\n",
+                    region.x0, col0, region.x1, col1);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid psRegion specified.  y0=%f=%d is greater than y1=%f=%d.\n",
+                    region.y0, row0, region.y1, row1);
+        }
+        return -1;
+    }/* else if (col0 == col1 && row0 == row1) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    "Invalid psRegion specified.  Region contains only 1 pixel.\n");
+            return -1;
+        }
+    */
+    x0 = col0;
+    x1 = col1;
+    y0 = row0;
+    y1 = row1;
 
     type = mask->type.type;
@@ -664,6 +773,6 @@
     case PS_TYPE_U8:
     case PS_TYPE_U16:
-        for (long j = y0; j < y1; j++) {
-            for (long i = x0; i < x1; i++) {
+        for (long j = y0; j <= y1; j++) {
+            for (long i = x0; i <= x1; i++) {
                 if (mask->data.PS_TYPE_MASK_DATA[j][i] & value) {
                     Npixels ++;
