Index: trunk/psLib/src/image/psImageExtraction.c
===================================================================
--- trunk/psLib/src/image/psImageExtraction.c	(revision 1864)
+++ trunk/psLib/src/image/psImageExtraction.c	(revision 1897)
@@ -10,6 +10,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-09-23 18:31:49 $
+*  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-09-25 02:06:12 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -609,6 +609,7 @@
 
 psVector* psImageCut(psVector* out,
-                     psVector* coords,
-                     const psImage* input,
+                     psVector* cutCols,
+                     psVector* cutRows,
+                     const psImage* in,
                      const psImage* restrict mask,
                      unsigned int maskVal,
@@ -620,10 +621,125 @@
                      psImageInterpolateMode mode)
 {
-
-    return NULL;
+    if (in == NULL || in->data.V == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_IMAGE_NULL);
+        psFree(out);
+        return NULL;
+    }
+    int numCols = in->numCols;
+    int numRows = in->numRows;
+
+    if (nSamples < 2) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_nSamples_TOOSMALL,
+                   nSamples);
+        psFree(out);
+        return NULL;
+    }
+
+    if (startCol < 0 || startCol >= numCols ||
+            startRow < 0 || startRow >= numRows ||
+            endCol < 0 || endCol >= numCols ||
+            endRow < 0 || endRow >= numRows) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_LINE_NOT_IN_IMAGE,
+                   startCol,startRow,endCol,endRow,
+                   numCols,numRows);
+        psFree(out);
+    }
+
+    if (mask != NULL) {
+        if (numRows != mask->numRows || numCols != mask->numCols) {
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                       PS_ERR_BAD_PARAMETER_VALUE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_SIZE,
+                       mask->numCols,mask->numRows,
+                       numCols, numRows);
+            psFree(out);
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_TYPE,
+                       typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+        }
+    }
+
+    //resize the vectors for the coordinate output
+    psF32* cutColsData = NULL;
+    psF32* cutRowsData = NULL;
+    if (cutCols != NULL) {
+        (void)psVectorRecycle(cutCols, nSamples, PS_TYPE_F32);
+        cutColsData = cutCols->data.F32;
+    }
+    if (cutRows != NULL) {
+        (void)psVectorRecycle(cutRows, nSamples, PS_TYPE_F32);
+        cutRowsData = cutRows->data.F32;
+    }
+
+    out = psVectorRecycle(out,nSamples,in->type.type);
+
+    float dX = (endCol - startCol) / (nSamples-1);
+    float dY = (endRow - startRow) / (nSamples-1);
+
+    float x = startCol;
+    float y = startRow;
+
+    #define LINEAR_CUT_CASE(TYPE) \
+case PS_TYPE_##TYPE: { \
+        ps##TYPE* outData = out->data.TYPE; \
+        for (int i = 0; i < nSamples; i++) { \
+            /* store off the location of the sample. */ \
+            if (cutColsData != NULL) { \
+                cutColsData[i] = x; \
+            } \
+            if (cutRowsData != NULL) { \
+                cutRowsData[i] = y; \
+            } \
+            outData[i] = psImagePixelInterpolate(in,x,y,mask,maskVal,0,mode); \
+            x += dX; \
+            y += dY; \
+        } \
+    } \
+    break;
+
+
+    switch (in->type.type) {
+        LINEAR_CUT_CASE(U8);
+        LINEAR_CUT_CASE(U16);
+        LINEAR_CUT_CASE(U32);
+        LINEAR_CUT_CASE(U64);
+        LINEAR_CUT_CASE(S8);
+        LINEAR_CUT_CASE(S16);
+        LINEAR_CUT_CASE(S32);
+        LINEAR_CUT_CASE(S64);
+        LINEAR_CUT_CASE(F32);
+        LINEAR_CUT_CASE(F64);
+        LINEAR_CUT_CASE(C32);
+        LINEAR_CUT_CASE(C64);
+
+    default: {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,in->type.type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageCut",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_TYPE_UNSUPPORTED,
+                       typeStr);
+            psFree(out);
+            out = NULL;
+        }
+    }
+
+    return out;
 }
 
 psVector* psImageRadialCut(psVector* out,
-                           const psImage* input,
+                           const psImage* in,
                            const psImage* restrict mask,
                            unsigned int maskVal,
@@ -633,5 +749,194 @@
                            const psStats* stats)
 {
-
-    return NULL;
+    double statVal;
+
+    /* check the parameters */
+
+    if (in == NULL || in->data.V == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_IMAGE_NULL);
+        psFree(out);
+        return NULL;
+    }
+    int numCols = in->numCols;
+    int numRows = in->numRows;
+
+    if (mask != NULL) {
+        if (numRows != mask->numRows || numCols != mask->numCols) {
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                       PS_ERR_BAD_PARAMETER_VALUE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_SIZE,
+                       mask->numCols,mask->numRows,
+                       numCols, numRows);
+            psFree(out);
+        }
+        if (mask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,mask->type.type);
+            psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                       PS_ERR_BAD_PARAMETER_TYPE, true,
+                       PS_ERRORTEXT_psImage_IMAGE_MASK_TYPE,
+                       typeStr, PS_TYPE_MASK_NAME);
+            psFree(out);
+        }
+    }
+
+    if (centerCol < 0 || centerCol >= numCols ||
+            centerRow < 0 || centerRow >= numRows) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_CENTER_NOT_IN_IMAGE,
+                   centerCol, centerRow,
+                   numCols, numRows);
+        psFree(out);
+    }
+
+    if (radii == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_RADII_VECTOR_NULL);
+        psFree(out);
+        return NULL;
+    }
+
+    if (radii->n < 2) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, true,
+                   PS_ERRORTEXT_psImage_RADII_VECTOR_TOOSMALL,
+                   radii->n);
+        psFree(out);
+        return NULL;
+    }
+
+    if (stats == NULL) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_NULL, true,
+                   PS_ERRORTEXT_psImage_STAT_NULL);
+        psFree(out);
+        return NULL;
+    }
+
+    // verify that the stats struct specifies a
+    // single stats operation
+    if (p_psGetStatValue(stats, &statVal) == false) {
+        psErrorMsg(PS_ERRORNAME_DOMAIN "psImageRadialCut",
+                   PS_ERR_BAD_PARAMETER_VALUE, false,
+                   PS_ERRORTEXT_psImage_BAD_STAT);
+        psFree(out);
+        return NULL;
+    }
+
+    /* completed checking the parameters */
+
+    // size the output vector to proper size.
+    int numOut = radii->n - 1;
+    out = psVectorRecycle(out, numOut, PS_TYPE_F64);
+    psF64* outData = out->data.F64;
+
+    // sort the radii by value
+    psVector* rSqVec = psVectorCopy(NULL, radii, PS_TYPE_F32);
+    psVectorSort(rSqVec,rSqVec);
+    psF32* rSq = rSqVec->data.F32;
+
+    int startRow = centerRow - rSq[numOut];
+    int endRow = centerRow + rSq[numOut];
+    int startCol = centerCol - rSq[numOut];
+    int endCol = centerCol + rSq[numOut];
+
+    if (startRow < 0) {
+        startRow = 0;
+    }
+
+    if (startCol < 0) {
+        startCol = 0;
+    }
+
+    if (endRow >= numRows) {
+        endRow = numRows - 1;
+    }
+
+    if (endCol >= numCols) {
+        endCol = numCols - 1;
+    }
+
+    // Square the data
+    for (int d = 0; d <= numOut; d++) {
+        rSq[d] *= rSq[d];
+    }
+
+    // create temporary vectors for the data binning step
+    psVector** buffer = psAlloc(sizeof(psVector*)*numOut);
+    psVector** bufferMask = psAlloc(sizeof(psVector*)*numOut);
+    for (int lcv = 0; lcv < numOut; lcv++) {
+        // n.b. alloc enough for the data by making the vectors slightly larger
+        // than the area of the region of interest.
+        buffer[lcv] = psVectorAlloc(1+4*(rSq[lcv+1]-rSq[lcv]),
+                                    in->type.type);
+        buffer[lcv]->n = 0;
+
+        bufferMask[lcv] = NULL;
+        if (mask != NULL) {
+            bufferMask[lcv] = psVectorAlloc(1+4*(rSq[lcv+1]-rSq[lcv]),
+                                            PS_TYPE_MASK);
+            bufferMask[lcv]->n = 0;
+        }
+    }
+
+    float dX;
+    float dY;
+    float dist;
+    for (int row=startRow; row <= endRow; row++) {
+        psF32* inRow = in->data.F32[row];
+        psMaskType* maskRow = NULL;
+        if (mask != NULL) {
+            maskRow = mask->data.PS_TYPE_MASK_DATA[row];
+        }
+        for (int col=startCol; col <= endCol; col++) {
+            dX = centerCol - (float)col - 0.5f;
+            dY = centerRow - (float)row - 0.5f;
+            dist = dX*dX+dY*dY;
+            for (int r = 0; r < numOut;) {
+                if (rSq[r] < dist && dist < rSq[++r]) {
+                    int n = buffer[r]->n;
+                    if (n == buffer[r]->nalloc) { // in case buffers already full, expand
+                        buffer[r] = psVectorRealloc(n*2, buffer[r]);
+                        if (bufferMask[r] != NULL) {
+                            bufferMask[r] = psVectorRealloc(n*2, bufferMask[r]);
+                        }
+                    }
+
+                    buffer[r]->data.F32[n] = inRow[col];
+                    buffer[r]->n = n+1;
+
+                    if (maskRow != NULL) {
+                        bufferMask[r]->data.PS_TYPE_MASK_DATA[n] = maskRow[col];
+                        bufferMask[r]->n = n+1;
+                    }
+
+                    break;
+                }
+            }
+        }
+    }
+
+    psStats* myStats = psAlloc(sizeof(psStats));
+    *myStats = *stats;
+
+    for (int r = 0; r < numOut; r++) {
+        myStats = psVectorStats(myStats,buffer[r], bufferMask[r],maskVal);
+        (void)p_psGetStatValue(myStats,&statVal);
+        outData[r] = statVal;
+    }
+
+    psFree(myStats);
+
+    for (int lcv = 0; lcv < numOut; lcv++) {
+        psFree(buffer[lcv]);
+        psFree(bufferMask[lcv]);
+    }
+    psFree(buffer);
+    psFree(bufferMask);
+
+    return out;
 }
