Index: trunk/psLib/test/image/tst_psImageExtraction.c
===================================================================
--- trunk/psLib/test/image/tst_psImageExtraction.c	(revision 2079)
+++ trunk/psLib/test/image/tst_psImageExtraction.c	(revision 2087)
@@ -6,6 +6,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-10-13 20:27:36 $
+*  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-10-13 22:04:29 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -22,4 +22,6 @@
 static int testImageSubsection(void);
 static int testImageTrim(void);
+static int testImageCut(void);
+static int testImageRadialCut(void);
 
 
@@ -30,4 +32,6 @@
                               {testImageSlice, 552, "psImageSlice", 0, false},
                               {testImageTrim, 744, "psImageTrim", 0, false},
+                              {testImageCut, 555, "psImageCut", 0, false},
+                              {testImageRadialCut, 557, "psImageRadialCut", 0, false},
                               {NULL}
                           };
@@ -45,10 +49,7 @@
     const int n = r / 4 -1;
     psVector* out = NULL;
-    psImage* image = psImageAlloc( c, r, PS_TYPE_F32 );
-    psImage* imgU8 = psImageAlloc( c, r, PS_TYPE_U8 );
+    psImage* image;
     psVector* positions = psVectorAlloc( r, PS_TYPE_U32 );
     psImage* mask = psImageAlloc( c, r, PS_TYPE_MASK );
-    psImage* maskS8 = psImageAlloc( c, r, PS_TYPE_S8 );
-    psImage* maskSz = psImageAlloc( r, c, PS_TYPE_MASK );
     psStats* stat = psStatsAlloc( PS_STAT_SAMPLE_MEDIAN );
 
@@ -68,20 +69,19 @@
 
     for ( int row = 0;row < r;row++ ) {
-        psF32* imageRow = image->data.F32[ row ];
-        psU8* imgU8Row = imgU8->data.U8[ row ];
-        psMaskType* maskRow = mask->data.V[ row ];
-        psMaskType* maskSzRow = maskSz->data.V[ row ];
-        psS8* maskS8Row = maskS8->data.V[ row ];
-        psF32 rowOffset = ( psF32 ) row / ( psF32 ) r;
+        psMaskType* maskRow = mask->data.PS_TYPE_MASK_DATA[row];
         for ( int col = 0;col < c;col++ ) {
-            imageRow[ col ] = ( psF32 ) col + rowOffset;
-            imgU8Row[ col ] = (psU8) col;
             maskRow[ col ] = 0;
-            maskS8Row[ col ] = 0;
-            maskSzRow[ col ] = 0;
-        }
-    }
-
-    #define PSIMAGESLICE_TEST1(M,N,DIRECTION,TRUTH_SIZE,TRUTHPIX_X,TRUTHPIX_Y,TESTNUM) \
+        }
+    }
+
+    #define PSIMAGESLICE_TEST1(TYPE,M,N,DIRECTION,TRUTH_SIZE,TRUTHPIX_X,TRUTHPIX_Y,TESTNUM) \
+    image = psImageAlloc( c, r, PS_TYPE_##TYPE ); \
+    for ( int row = 0;row < r;row++ ) { \
+        ps##TYPE *imageRow = image->data.TYPE[ row ]; \
+        ps##TYPE rowOffset = row * 2; \
+        for ( int col = 0;col < c;col++ ) { \
+            imageRow[ col ] = col + rowOffset; \
+        } \
+    } \
     out = psImageSlice(out,positions,image,mask,1,c/10,r/10,c/10+M,r/10+N,DIRECTION,stat); \
     \
@@ -117,29 +117,30 @@
             } \
         } \
-    }
+    } \
+    psFree(image);
 
     // test MxN case
-    PSIMAGESLICE_TEST1( m, n, PS_CUT_X_POS, m, i, n / 2, 0 );
-    PSIMAGESLICE_TEST1( m, n, PS_CUT_X_NEG, m, m - 1 - i, n / 2, 1 );
-    PSIMAGESLICE_TEST1( m, n, PS_CUT_Y_POS, n, m / 2, i, 2 );
-    PSIMAGESLICE_TEST1( m, n, PS_CUT_Y_NEG, n, m / 2, n - 1 - i, 3 );
+    PSIMAGESLICE_TEST1(F32, m, n, PS_CUT_X_POS, m, i, n / 2, 0 );
+    PSIMAGESLICE_TEST1(F32, m, n, PS_CUT_X_NEG, m, m - 1 - i, n / 2, 1 );
+    PSIMAGESLICE_TEST1(F32, m, n, PS_CUT_Y_POS, n, m / 2, i, 2 );
+    PSIMAGESLICE_TEST1(F32, m, n, PS_CUT_Y_NEG, n, m / 2, n - 1 - i, 3 );
 
     // test Mx1 case
-    PSIMAGESLICE_TEST1( m, 1, PS_CUT_X_POS, m, i, 0, 4 );
-    PSIMAGESLICE_TEST1( m, 1, PS_CUT_X_NEG, m, m - 1 - i, 0, 5 );
-    PSIMAGESLICE_TEST1( m, 1, PS_CUT_Y_POS, 1, m / 2, 0, 6 );
-    PSIMAGESLICE_TEST1( m, 1, PS_CUT_Y_NEG, 1, m / 2, 0, 7 );
+    PSIMAGESLICE_TEST1(F32, m, 1, PS_CUT_X_POS, m, i, 0, 4 );
+    PSIMAGESLICE_TEST1(F32, m, 1, PS_CUT_X_NEG, m, m - 1 - i, 0, 5 );
+    PSIMAGESLICE_TEST1(F32, m, 1, PS_CUT_Y_POS, 1, m / 2, 0, 6 );
+    PSIMAGESLICE_TEST1(F32, m, 1, PS_CUT_Y_NEG, 1, m / 2, 0, 7 );
 
     // test 1xN case
-    PSIMAGESLICE_TEST1( 1, n, PS_CUT_X_POS, 1, 0, n / 2, 8 );
-    PSIMAGESLICE_TEST1( 1, n, PS_CUT_X_NEG, 1, 0, n / 2, 9 );
-    PSIMAGESLICE_TEST1( 1, n, PS_CUT_Y_POS, n, 0, i, 10 );
-    PSIMAGESLICE_TEST1( 1, n, PS_CUT_Y_NEG, n, 0, n - 1 - i, 11 );
+    PSIMAGESLICE_TEST1(F32, 1, n, PS_CUT_X_POS, 1, 0, n / 2, 8 );
+    PSIMAGESLICE_TEST1(F32, 1, n, PS_CUT_X_NEG, 1, 0, n / 2, 9 );
+    PSIMAGESLICE_TEST1(F32, 1, n, PS_CUT_Y_POS, n, 0, i, 10 );
+    PSIMAGESLICE_TEST1(F32, 1, n, PS_CUT_Y_NEG, n, 0, n - 1 - i, 11 );
 
     // test 1x1 case
-    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_X_POS, 1, 0, 0, 12 );
-    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_X_NEG, 1, 0, 0, 13 );
-    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_Y_POS, 1, 0, 0, 14 );
-    PSIMAGESLICE_TEST1( 1, 1, PS_CUT_Y_NEG, 1, 0, 0, 15 );
+    PSIMAGESLICE_TEST1(F32, 1, 1, PS_CUT_X_POS, 1, 0, 0, 12 );
+    PSIMAGESLICE_TEST1(F32, 1, 1, PS_CUT_X_NEG, 1, 0, 0, 13 );
+    PSIMAGESLICE_TEST1(F32, 1, 1, PS_CUT_Y_POS, 1, 0, 0, 14 );
+    PSIMAGESLICE_TEST1(F32, 1, 1, PS_CUT_Y_NEG, 1, 0, 0, 15 );
 
     /*
@@ -298,4 +299,5 @@
     psLogMsg( __func__, PS_LOG_INFO, "Following should be an error mask size != image size.");
     stat->options = PS_STAT_SAMPLE_MEDIAN;
+    psImage* maskSz = psImageAlloc( r, c, PS_TYPE_MASK );
     out = psImageSlice( out, NULL,
                         image,
@@ -313,4 +315,5 @@
     */
     psLogMsg( __func__, PS_LOG_INFO, "Following should be an error invalid mask type.");
+    psImage* maskS8 = psImageAlloc( c, r, PS_TYPE_S8 );
     out =  psImageSlice( out, NULL,
                          image,
@@ -327,4 +330,5 @@
     /* Verify the input image is an invalid type */
     psLogMsg( __func__, PS_LOG_INFO, "Following should be an error invalid image type.");
+    psImage* imgU8 = psImageAlloc( c, r, PS_TYPE_U8 );
     out = psImageSlice( out, NULL,
                         imgU8,
@@ -881,5 +885,5 @@
             c. appropriate error is generated.
     */
-    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL image.");
+
     image2 = psImageTrim(NULL,qtrC,qtrR,0,0);
 
@@ -899,5 +903,4 @@
 
     image1 = psImageCopy(NULL,image,PS_TYPE_F32);
-    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for trim outside.");
     image2 = psImageTrim(image1,-1,0,0,0);
 
@@ -917,5 +920,4 @@
 
     image1 = psImageCopy(NULL,image,PS_TYPE_F32);
-    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for trim outside.");
     image2 = psImageTrim(image1,0,-1,0,0);
 
@@ -935,5 +937,4 @@
 
     image1 = psImageCopy(NULL,image,PS_TYPE_F32);
-    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for trim outside.");
     image2 = psImageTrim(image1,0,0,image->numCols+1,0);
 
@@ -953,5 +954,4 @@
 
     image1 = psImageCopy(NULL,image,PS_TYPE_F32);
-    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for trim outside.");
     image2 = psImageTrim(image1,0,0,0,image->numRows+1);
 
@@ -971,5 +971,4 @@
 
     image1 = psImageCopy(NULL,image,PS_TYPE_F32);
-    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for trim outside.");
     image2 = psImageTrim(image1,0,0,-image->numCols,0);
 
@@ -989,5 +988,4 @@
 
     image1 = psImageCopy(NULL,image,PS_TYPE_F32);
-    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for trim outside.");
     image2 = psImageTrim(image1,0,0,0,-image->numRows);
 
@@ -1009,2 +1007,173 @@
     return 0;
 }
+
+static int testImageCut(void)
+{
+    // XXX - fill in
+    int c = 300;
+    int r = 200;
+    int numPoints = 15;
+    float startCol[] = { 40,150, 40,  0,280, 40,280, -1,300, 20, 20, 20, 20, 20, 20};
+    float endCol[] =   {240,150,240,299, 40,240, 40,240,240, -1,300,240,240,240,240};
+    float startRow[] = { 20, 10,100,  0, 20,180,180, 10, 10, 10, 10, -1,200, 10, 10};
+    float endRow[] =   {160,180,100,199,160, 10, 10,180,180,180,180,180,180, -1,200};
+    bool success[] = {true,true,true,true,true,true,true,false,false,false,false,false,false,false,false};
+    unsigned int length = 100;
+
+    psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+    psImage* mask = psImageAlloc(c,r,PS_TYPE_MASK);
+    for (int row = 0; row < image->numRows; row++) {
+        for (int col = 0; col < image->numCols; col++) {
+            image->data.F32[row][col] = (psF32)col + (psF32)row/1000.0f;
+            if ((row & 0x0F) == 0) {
+                mask->data.PS_TYPE_MASK_DATA[row][col] = 1;
+            } else {
+                mask->data.PS_TYPE_MASK_DATA[row][col] = 0;
+            }
+        }
+    }
+    psVector* rows = psVectorAlloc(length,PS_TYPE_F32);
+    psVector* cols = psVectorAlloc(length,PS_TYPE_F32);
+
+    psVector* result = NULL;
+    for (int n = 0; n < numPoints; n++) {
+        psVector* orig = result;
+        if (! success[n]) {
+            psLogMsg(__func__,PS_LOG_INFO,"The following should be an error.");
+        }
+        if (n == 1) {
+            result = psImageCut(result,
+                                cols,rows,
+                                image,
+                                NULL,0,
+                                startCol[n], startRow[n],
+                                endCol[n], endRow[n],
+                                length,
+                                PS_INTERPOLATE_FLAT);
+        } else {
+            result = psImageCut(result,
+                                cols,rows,
+                                image,
+                                mask,1,
+                                startCol[n], startRow[n],
+                                endCol[n], endRow[n],
+                                length,
+                                PS_INTERPOLATE_FLAT);
+        }
+
+        if (success[n]) {
+            if (result == NULL) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut returned NULL instead of a valid result.");
+                return n*10+1;
+            }
+
+            if (orig != NULL && orig != result) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut didn't recycle the out parameter properly.");
+                return n*10+2;
+            }
+
+            float deltaRow = (endRow[n]-startRow[n])/(length-1);
+            float deltaCol = (endCol[n]-startCol[n])/(length-1);
+            psF32 truth;
+            for (int i = 0; i < length; i++) {
+                float x = (float)startCol[n]+(float)i*deltaCol;
+                float y = (float)startRow[n]+(float)i*deltaRow;
+                if (n == 1) {
+                    truth = psImagePixelInterpolate( image, x, y,
+                                                     NULL,0,0,PS_INTERPOLATE_FLAT);
+                } else {
+                    truth = psImagePixelInterpolate( image, x, y,
+                                                     mask,1,0,PS_INTERPOLATE_FLAT);
+                }
+                if (fabs(result->data.F32[i]-truth) > FLT_EPSILON) {
+                    psLogMsg(__func__,PS_LOG_ERROR,
+                             "Bad result in position %d; Found %g but expected %g.",
+                             i, result->data.F32[i], truth);
+                    return n*10+5;
+                }
+                if (fabsf(x - cols->data.F32[i]) > FLT_EPSILON ||
+                        fabsf(y - rows->data.F32[i]) > FLT_EPSILON) {
+                    psLogMsg(__func__,PS_LOG_ERROR,
+                             "Bad resulting col/row at index %d; Found (%g,%g) but expected (%g,%g).",
+                             i, cols->data.F32[i], rows->data.F32[i], x, y);
+                    return n*10+6;
+                }
+            }
+        } else {
+            if (result != NULL) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut did not return NULL with a cut of (%g,%g)->(%g,%g).",
+                         startCol[n],startRow[n],endCol[n],endRow[n]);
+                return n*10+7;
+            }
+            psErr* err = psErrorLast();
+            if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+                psLogMsg(__func__,PS_LOG_ERROR,
+                         "psImageCut did not generate proper error message.");
+                return 105;
+            }
+            psFree(err);
+        }
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (NULL image).");
+    result = psImageCut(result,
+                        cols,rows,
+                        NULL,
+                        mask,1,
+                        startCol[0], startRow[0],
+                        endCol[0], endRow[0],
+                        length,
+                        PS_INTERPOLATE_FLAT);
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not return NULL given NULL image.");
+        return 100;
+    }
+    psErr* err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not generate proper error message given NULL image.");
+        return 101;
+    }
+    psFree(err);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be an error (length=0).");
+    result = psImageCut(result,
+                        cols,rows,
+                        image,
+                        mask,1,
+                        startCol[0], startRow[0],
+                        endCol[0], endRow[0],
+                        0,
+                        PS_INTERPOLATE_FLAT);
+    if (result != NULL) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not return NULL given length=0.");
+        return 102;
+    }
+    err = psErrorLast();
+    if (err->code != PS_ERR_BAD_PARAMETER_VALUE) {
+        psLogMsg(__func__,PS_LOG_ERROR,
+                 "psImageCut did not generate proper error message given length=0.");
+        return 103;
+    }
+    psFree(err);
+
+    psFree(result);
+    psFree(image);
+    psFree(mask);
+    psFree(rows);
+    psFree(cols);
+
+    return 0;
+}
+
+static int testImageRadialCut(void)
+{
+    // XXX - fill in
+
+    return 0;
+}
