Index: trunk/psLib/src/image/psImageExtraction.c
===================================================================
--- trunk/psLib/src/image/psImageExtraction.c	(revision 1292)
+++ trunk/psLib/src/image/psImageExtraction.c	(revision 1359)
@@ -1,18 +1,18 @@
 /** @file  psImageManip.h
- *
- *  @brief Contains basic image extraction operations, as specified in the 
- *         PSLIB SDRS sections "Image Pixel Extractions" and "Image Structure
- *         Manipulation".
- *
- *  @ingroup Image
- *
- *  @author Robert DeSonia, MHPCC
- *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-07-24 02:00:21 $
- *
- *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
- *
- */
+*
+*  @brief Contains basic image extraction operations, as specified in the 
+*         PSLIB SDRS sections "Image Pixel Extractions" and "Image Structure
+*         Manipulation".
+*
+*  @ingroup Image
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-07-31 02:27:43 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
 
 #include <string.h>
@@ -22,72 +22,72 @@
 #include "psError.h"
 
-psImage *psImageSubset(psImage *out,psImage *image,unsigned int numCols,
-                       unsigned int numRows, unsigned int col0,
-                       unsigned int row0)
+psImage *psImageSubset( psImage *out, psImage *image, unsigned int numCols,
+                        unsigned int numRows, unsigned int col0,
+                        unsigned int row0 )
 {
     unsigned int elementSize;           // size of image element in bytes
     unsigned int outputRowSize;         // output row size in bytes
     unsigned int inputColOffset;        // offset in bytes to first subset pixel in input row
-
-    if (image == NULL || image->data.V == NULL) {
-        psError(__func__,"Can not subset image because input image or its pixel buffer is NULL.");
-        return NULL;
-    }
-
-    if (image->type.dimen != PS_DIMEN_IMAGE) {
-        psError(__func__,"Can not subset image because input image is not an image.");
-        return NULL;
-    }
-
-    if (numCols < 1 || numRows < 1) {
-        psError(__func__,"Can not subset image because number of rows or columns are zero (%dx%d).",
-                numCols, numRows);
-        return NULL;
-    }
-
-    if (col0 >= image->numCols || row0 >= image->numRows) {
-        psError(__func__,"Can not subset image because col0,row0 (%d,%d) is not a valid pixel location.",
-                col0,row0);
-        return NULL;
-    }
-
+    
+    if ( image == NULL || image->data.V == NULL ) {
+            psError( __func__, "Can not subset image because input image or its pixel buffer is NULL." );
+            return NULL;
+        }
+        
+    if ( image->type.dimen != PS_DIMEN_IMAGE ) {
+            psError( __func__, "Can not subset image because input image is not an image." );
+            return NULL;
+        }
+        
+    if ( numCols < 1 || numRows < 1 ) {
+            psError( __func__, "Can not subset image because number of rows or columns are zero (%dx%d).",
+                     numCols, numRows );
+            return NULL;
+        }
+        
+    if ( col0 >= image->numCols || row0 >= image->numRows ) {
+            psError( __func__, "Can not subset image because col0,row0 (%d,%d) is not a valid pixel location.",
+                     col0, row0 );
+            return NULL;
+        }
+        
     /* validate subimage size */
-    if (col0+numCols >= image->numCols || row0+numRows >= image->numRows) {
-        psError(__func__,"Can not subset image outside of image boundaries (size=%dx%d, "
-                "subset=[%d:%d,%d:%d]).",image->numCols,image->numRows,col0,
-                col0+numCols, row0, row0+numRows);
-        return NULL;
-    }
-
-
-    elementSize = PSELEMTYPE_SIZEOF(image->type.type);
-
-    out = psImageRecycle(out,numCols,numRows,image->type.type);
-
+    if ( col0 + numCols >= image->numCols || row0 + numRows >= image->numRows ) {
+            psError( __func__, "Can not subset image outside of image boundaries (size=%dx%d, "
+                     "subset=[%d:%d,%d:%d]).", image->numCols, image->numRows, col0,
+                     col0 + numCols, row0, row0 + numRows );
+            return NULL;
+        }
+        
+        
+    elementSize = PSELEMTYPE_SIZEOF( image->type.type );
+    
+    out = psImageRecycle( out, numCols, numRows, image->type.type );
+    
     // set the parent information into the child output image
-    *(int*)&out->row0 = row0;
-    *(int*)&out->col0 = col0;
-    *(psImage**)&out->parent = (psImage*)image;
-
+    *( int* ) & out->row0 = row0;
+    *( int* ) & out->col0 = col0;
+    *( psImage** ) & out->parent = ( psImage* ) image;
+    
     // add output image as a child of the input image.
     image->nChildren++;
-    image->children = (psImage **) psRealloc(image->children,
-                      image->nChildren * sizeof(psImage*) );
-    image->children[image->nChildren-1] = out;
-
-    inputColOffset = elementSize*col0;
-    outputRowSize = elementSize*numCols;
-
-    for (int row = 0; row < numRows; row++) {
-        memcpy(out->data.V[row],image->data.U8[row0+row] + inputColOffset,
-               outputRowSize);
-    }
-
-    return (out);
+    image->children = ( psImage ** ) psRealloc( image->children,
+                      image->nChildren * sizeof( psImage* ) );
+    image->children[ image->nChildren - 1 ] = out;
+    
+    inputColOffset = elementSize * col0;
+    outputRowSize = elementSize * numCols;
+    
+    for ( int row = 0; row < numRows; row++ ) {
+            memcpy( out->data.V[ row ], image->data.U8[ row0 + row ] + inputColOffset,
+                    outputRowSize );
+        }
+        
+    return ( out );
 }
 
 
-psImage *psImageCopy(psImage* restrict output, const psImage *input,
-                     psElemType type)
+psImage *psImageCopy( psImage* restrict output, const psImage *input,
+                      psElemType type )
 {
     psElemType inDatatype;
@@ -96,147 +96,147 @@
     int numRows;
     int numCols;
-
-    if (input == NULL || input->data.V == NULL) {
-        psError(__func__,"Can not copy image because input image or its pixel buffer is NULL.");
-        psFree(output);
-        return NULL;
-    }
-
-    if (input == output) {
-        psError(__func__,"Can not copy image because given input and output "
-                "parameter reference the same psImage struct.");
-        psFree(output);
-        return NULL;
-    }
-
-    if (input->type.dimen != PS_DIMEN_IMAGE) {
-        psError(__func__,"Can not copy image because input image is not actually an image.");
-        psFree(output);
-        return NULL;
-    }
-
+    
+    if ( input == NULL || input->data.V == NULL ) {
+            psError( __func__, "Can not copy image because input image or its pixel buffer is NULL." );
+            psFree( output );
+            return NULL;
+        }
+        
+    if ( input == output ) {
+            psError( __func__, "Can not copy image because given input and output "
+                     "parameter reference the same psImage struct." );
+            psFree( output );
+            return NULL;
+        }
+        
+    if ( input->type.dimen != PS_DIMEN_IMAGE ) {
+            psError( __func__, "Can not copy image because input image is not actually an image." );
+            psFree( output );
+            return NULL;
+        }
+        
     inDatatype = input->type.type;
     numRows = input->numRows;
     numCols = input->numCols;
-    elements = numRows*numCols;
-    elementSize = PSELEMTYPE_SIZEOF(inDatatype);
-
-    if (inDatatype == PS_TYPE_PTR || type == PS_TYPE_PTR) {
-        psError(__func__,"Can not copy image to/from a void* matrix");
-        psFree(output);
-        return NULL;
-    }
-
-    output = psImageRecycle(output,numCols,numRows,type);
-
+    elements = numRows * numCols;
+    elementSize = PSELEMTYPE_SIZEOF( inDatatype );
+    
+    if ( inDatatype == PS_TYPE_PTR || type == PS_TYPE_PTR ) {
+            psError( __func__, "Can not copy image to/from a void* matrix" );
+            psFree( output );
+            return NULL;
+        }
+        
+    output = psImageRecycle( output, numCols, numRows, type );
+    
     // cover the trival case of copy of the same datatype.
-    if (type == inDatatype) {
-        memcpy(output->data.V[0],input->data.V[0],elementSize*elements);
-        return output;
-    }
-
+    if ( type == inDatatype ) {
+            memcpy( output->data.V[ 0 ], input->data.V[ 0 ], elementSize * elements );
+            return output;
+        }
+        
     #define PSIMAGE_ELEMENT_COPY(IN,INTYPE,OUT,OUTTYPE,ELEMENTS) { \
         ps##INTYPE *in = IN->data.INTYPE[0]; \
         ps##OUTTYPE *out = OUT->data.OUTTYPE[0]; \
         for (int e=0;e<ELEMENTS;e++) { \
-            *(out++) = *(in++); \
-        } \
+                *(out++) = *(in++); \
+            } \
     }
-
+    
     #define PSIMAGE_COPY_CASE(OUT,OUTTYPE) \
     switch (inDatatype) { \
-    case PS_TYPE_S8: \
-        PSIMAGE_ELEMENT_COPY(input,S8,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_S16: \
-        PSIMAGE_ELEMENT_COPY(input,S16,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_S32: \
-        PSIMAGE_ELEMENT_COPY(input,S32,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_S64: \
-        PSIMAGE_ELEMENT_COPY(input,S64,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_U8: \
-        PSIMAGE_ELEMENT_COPY(input,U8,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_U16: \
-        PSIMAGE_ELEMENT_COPY(input,U16,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_U32: \
-        PSIMAGE_ELEMENT_COPY(input,U32,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_U64: \
-        PSIMAGE_ELEMENT_COPY(input,U64,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_F32: \
-        PSIMAGE_ELEMENT_COPY(input,F32,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_F64: \
-        PSIMAGE_ELEMENT_COPY(input,F64,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_C32: \
-        PSIMAGE_ELEMENT_COPY(input,C32,OUT,OUTTYPE,elements); \
-        break; \
-    case PS_TYPE_C64: \
-        PSIMAGE_ELEMENT_COPY(input,C64,OUT,OUTTYPE,elements); \
-        break; \
-    default: \
-        break; \
-    }
-
-    switch (type) {
-    case PS_TYPE_S8:
-        PSIMAGE_COPY_CASE(output,S8);
-        break;
-    case PS_TYPE_S16:
-        PSIMAGE_COPY_CASE(output,S16);
-        break;
-    case PS_TYPE_S32:
-        PSIMAGE_COPY_CASE(output,S32);
-        break;
-    case PS_TYPE_S64:
-        PSIMAGE_COPY_CASE(output,S64);
-        break;
-    case PS_TYPE_U8:
-        PSIMAGE_COPY_CASE(output,U8);
-        break;
-    case PS_TYPE_U16:
-        PSIMAGE_COPY_CASE(output,U16);
-        break;
-    case PS_TYPE_U32:
-        PSIMAGE_COPY_CASE(output,U32);
-        break;
-    case PS_TYPE_U64:
-        PSIMAGE_COPY_CASE(output,U64);
-        break;
-    case PS_TYPE_F32:
-        PSIMAGE_COPY_CASE(output,F32);
-        break;
-    case PS_TYPE_F64:
-        PSIMAGE_COPY_CASE(output,F64);
-        break;
-    case PS_TYPE_C32:
-        PSIMAGE_COPY_CASE(output,C32);
-        break;
-    case PS_TYPE_C64:
-        PSIMAGE_COPY_CASE(output,C64);
-        break;
-    default:
-        break;
-    }
+            case PS_TYPE_S8: \
+            PSIMAGE_ELEMENT_COPY(input,S8,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_S16: \
+            PSIMAGE_ELEMENT_COPY(input,S16,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_S32: \
+            PSIMAGE_ELEMENT_COPY(input,S32,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_S64: \
+            PSIMAGE_ELEMENT_COPY(input,S64,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_U8: \
+            PSIMAGE_ELEMENT_COPY(input,U8,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_U16: \
+            PSIMAGE_ELEMENT_COPY(input,U16,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_U32: \
+            PSIMAGE_ELEMENT_COPY(input,U32,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_U64: \
+            PSIMAGE_ELEMENT_COPY(input,U64,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_F32: \
+            PSIMAGE_ELEMENT_COPY(input,F32,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_F64: \
+            PSIMAGE_ELEMENT_COPY(input,F64,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_C32: \
+            PSIMAGE_ELEMENT_COPY(input,C32,OUT,OUTTYPE,elements); \
+            break; \
+            case PS_TYPE_C64: \
+            PSIMAGE_ELEMENT_COPY(input,C64,OUT,OUTTYPE,elements); \
+            break; \
+            default: \
+            break; \
+        }
+        
+    switch ( type ) {
+            case PS_TYPE_S8:
+            PSIMAGE_COPY_CASE( output, S8 );
+            break;
+            case PS_TYPE_S16:
+            PSIMAGE_COPY_CASE( output, S16 );
+            break;
+            case PS_TYPE_S32:
+            PSIMAGE_COPY_CASE( output, S32 );
+            break;
+            case PS_TYPE_S64:
+            PSIMAGE_COPY_CASE( output, S64 );
+            break;
+            case PS_TYPE_U8:
+            PSIMAGE_COPY_CASE( output, U8 );
+            break;
+            case PS_TYPE_U16:
+            PSIMAGE_COPY_CASE( output, U16 );
+            break;
+            case PS_TYPE_U32:
+            PSIMAGE_COPY_CASE( output, U32 );
+            break;
+            case PS_TYPE_U64:
+            PSIMAGE_COPY_CASE( output, U64 );
+            break;
+            case PS_TYPE_F32:
+            PSIMAGE_COPY_CASE( output, F32 );
+            break;
+            case PS_TYPE_F64:
+            PSIMAGE_COPY_CASE( output, F64 );
+            break;
+            case PS_TYPE_C32:
+            PSIMAGE_COPY_CASE( output, C32 );
+            break;
+            case PS_TYPE_C64:
+            PSIMAGE_COPY_CASE( output, C64 );
+            break;
+            default:
+            break;
+        }
     return output;
 }
 
-psVector* psImageSlice(psVector* out,
-                       const psImage* in,
-                       const psImage* restrict mask,
-                       unsigned int maskVal,
-                       unsigned int col,
-                       unsigned int row,
-                       unsigned int numCols,
-                       unsigned int numRows,
-                       psImageCutDirection direction,
-                       const psStats* stats)
+psVector* psImageSlice( psVector* out,
+                        const psImage* restrict in,
+                        const psImage* restrict mask,
+                        unsigned int maskVal,
+                        unsigned int col,
+                        unsigned int row,
+                        unsigned int numCols,
+                        unsigned int numRows,
+                        psImageCutDirection direction,
+                        const psStats* stats )
 {
     double statVal;
@@ -247,153 +247,181 @@
     int delta = 1;
     psF64* outData;
-
-    if (in == NULL || in->data.V == NULL) {
-        psError(__func__,"Input image can not be NULL.");
-        psFree(out);
-        return NULL;
-    }
-
+    
+    if ( in == NULL || in->data.V == NULL ) {
+            psError( __func__, "Input image can not be NULL." );
+            psFree( out );
+            return NULL;
+        }
+        
+    if ( numRows == 0 || numCols == 0 ) {
+            psError( __func__, "The specified region contains no data (%dx%d)",
+                     numCols, numRows );
+            psFree( out );
+            return NULL;
+        }
+        
     type = in->type.type;
     inRows = in->numRows;
     inCols = in->numCols;
-
-    if (mask != NULL) {
-        if (inRows!=mask->numRows || inCols!=mask->numCols) {
-            psError(__func__,"The mask and image dimensions did not match (%dx%d vs %dx%d)",
-                    mask->numCols,mask->numRows,in->numCols,in->numRows);
-            psFree(out);
-        }
-        if (mask->type.type != PS_TYPE_MASK) {
-            psError(__func__,"The mask datatype (%d) must be %s.",
-                    mask->type.type, PS_TYPE_MASK_NAME);
-            psFree(out);
-        }
-    }
-
-    if (row >= inRows || col >= inCols ||
-            col+numCols > in->numCols || row+numRows > in->numRows) {
-        psError(__func__,"The specified image region (%d,%d to %d,%d) is outside of image area (0,0 to %d,%d).",
-                col, row, col+numCols-1, row+numRows-1, in->numCols-1, in->numRows-1);
-        psFree(out);
-        return NULL;
-    }
-
+    
+    if ( direction == PS_CUT_X_NEG || direction == PS_CUT_Y_NEG ) {
+            delta = -1;
+        }
+        
+    // if numRows/numCols is negative, invert the problem to give positive
+    // numRows/numCols (and cut in opposite direction).
+    if ( numRows < 0 ) {
+            numRows = -numRows;
+            row -= ( numRows - 1 );
+            delta = -delta;
+        }
+        
+    if ( numCols < 0 ) {
+            numCols = -numCols;
+            col -= ( numCols - 1 );
+            delta = -delta;
+        }
+        
+    if ( mask != NULL ) {
+            if ( inRows != mask->numRows || inCols != mask->numCols ) {
+                    psError( __func__, "The mask and image dimensions did not match (%dx%d vs %dx%d)",
+                             mask->numCols, mask->numRows, in->numCols, in->numRows );
+                    psFree( out );
+                }
+            if ( mask->type.type != PS_TYPE_MASK ) {
+                    psError( __func__, "The mask datatype (%d) must be %s.",
+                             mask->type.type, PS_TYPE_MASK_NAME );
+                    psFree( out );
+                }
+        }
+        
+    if ( row >= inRows || col >= inCols ||
+            col + numCols > in->numCols || row + numRows > in->numRows ) {
+            psError( __func__, "The specified image region (%d,%d to %d,%d) is outside of image area (0,0 to %d,%d).",
+                     col, row, col + numCols - 1, row + numRows - 1, in->numCols - 1, in->numRows - 1 );
+            psFree( out );
+            return NULL;
+        }
+        
     // verify that the stats struct specifies a single stats operation
-    if (p_psGetStatValue(stats,&statVal) == false) {
-        psError(__func__,"The stat options didn't specify a single supported statistic type.");
-        psFree(out);
-        return NULL;
-    }
-
+    if ( stats == NULL || p_psGetStatValue( stats, &statVal ) == false ) {
+            psError( __func__, "The stat options didn't specify a single supported statistic type." );
+            psFree( out );
+            return NULL;
+        }
+        
     // since stats input is const, I need to create a 'scratch' stats struct
-    myStats = psAlloc(sizeof(psStats));
+    myStats = psAlloc( sizeof( psStats ) );
     *myStats = *stats;
-
-
-    if (direction == PS_CUT_X_NEG || direction == PS_CUT_Y_NEG) {
-        delta = -1;
-    }
-
-    if (direction == PS_CUT_X_POS || direction == PS_CUT_X_NEG) {
-        psVector* imgVec = psVectorAlloc(numRows,type);
-        psVector* maskVec = NULL;
-        psMaskType* maskData = NULL;
-
-        // recycle output to make a proper sized/type output structure
-        // n.b. type is double as that is the type given for all stats in psStats.
-        out = psVectorRecycle(out,numCols,PS_TYPE_F64);
-        outData = out->data.F64;
-        if (delta < 0) {
-            outData += numCols - 1;
-        }
-
-        if (mask != NULL) {
-            maskVec = psVectorAlloc(numRows,mask->type.type);
-        }
-
-        #define PSIMAGE_CUT_VERTICAL(TYPE) \
-    case PS_TYPE_##TYPE: { \
-            ps##TYPE *imgVecData = imgVec->data.TYPE; \
-            psMaskType* maskVecData = NULL; \
-            if (maskVec != NULL) { \
-                maskVecData = maskVec->data.V; \
-            } \
-            for (int c=0;c<numCols;c++) { \
-                ps##TYPE *imgData = in->data.TYPE[row] + col + c; \
-                if (maskVec != NULL) { \
-                    maskData = (psMaskType*)(mask->data.V[row]) + col + c; \
-                } \
-                for (int r=0;r<numRows;r++) { \
-                    *(imgVecData++) = *imgData; \
-                    imgData += inCols; \
-                    if (maskVecData != NULL) { \
-                        *(maskVecData++) = *maskData; \
-                        maskData += inCols; \
+    
+    
+    
+    if ( direction == PS_CUT_X_POS || direction == PS_CUT_X_NEG ) {
+            psVector * imgVec = psVectorAlloc( numRows, type );
+            psVector* maskVec = NULL;
+            psMaskType* maskData = NULL;
+            
+            // recycle output to make a proper sized/type output structure
+            // n.b. type is double as that is the type given for all stats in psStats.
+            out = psVectorRecycle( out, PS_TYPE_F64, numCols );
+            outData = out->data.F64;
+            if ( delta < 0 ) {
+                    outData += numCols - 1;
+                }
+                
+            if ( mask != NULL ) {
+                    maskVec = psVectorAlloc( numRows, mask->type.type );
+                }
+                
+            #define PSIMAGE_CUT_VERTICAL(TYPE) \
+            case PS_TYPE_##TYPE: { \
+                psMaskType* maskVecData = NULL; \
+                for (int c=0;c<numCols;c++) { \
+                        ps##TYPE *imgData = in->data.TYPE[row] + col + c; \
+                        ps##TYPE *imgVecData = imgVec->data.TYPE; \
+                        if (maskVec != NULL) { \
+                                maskVecData = maskVec->data.V; \
+                                maskData = (psMaskType*)(mask->data.V[row]) + col + c; \
+                            } \
+                        for (int r=0;r<numRows;r++) { \
+                                *(imgVecData++) = *imgData; \
+                                imgData += inCols; \
+                                if (maskVecData != NULL) { \
+                                        *(maskVecData++) = *maskData; \
+                                        maskData += inCols; \
+                                    } \
+                            } \
+                        myStats = psVectorStats(myStats,imgVec,maskVec,maskVal); \
+                        (void)p_psGetStatValue(myStats,&statVal); \
+                        *outData = statVal; \
+                        outData += delta; \
                     } \
-                } \
-                myStats = psVectorStats(myStats,imgVec,maskVec,maskVal); \
-                (void)p_psGetStatValue(myStats,&statVal); \
-                *outData = statVal; \
-                outData += delta; \
-            } \
-            break; \
-        }
-
-        switch (type) {
-            PSIMAGE_CUT_VERTICAL(U8);
-            PSIMAGE_CUT_VERTICAL(U16);
-            PSIMAGE_CUT_VERTICAL(U32);
-            PSIMAGE_CUT_VERTICAL(U64);
-            PSIMAGE_CUT_VERTICAL(S8);
-            PSIMAGE_CUT_VERTICAL(S16);
-            PSIMAGE_CUT_VERTICAL(S32);
-            PSIMAGE_CUT_VERTICAL(S64);
-            PSIMAGE_CUT_VERTICAL(F32);
-            PSIMAGE_CUT_VERTICAL(F64);
-            PSIMAGE_CUT_VERTICAL(C32);
-            PSIMAGE_CUT_VERTICAL(C64);
-        default:
-            psError(__func__,"Unsupported datatype (%d)",type);
-            psFree(out);
+                break; \
+            }
+            
+            switch ( type ) {
+                    PSIMAGE_CUT_VERTICAL( U8 );
+                    PSIMAGE_CUT_VERTICAL( U16 );
+                    PSIMAGE_CUT_VERTICAL( U32 );
+                    PSIMAGE_CUT_VERTICAL( U64 );
+                    PSIMAGE_CUT_VERTICAL( S8 );
+                    PSIMAGE_CUT_VERTICAL( S16 );
+                    PSIMAGE_CUT_VERTICAL( S32 );
+                    PSIMAGE_CUT_VERTICAL( S64 );
+                    PSIMAGE_CUT_VERTICAL( F32 );
+                    PSIMAGE_CUT_VERTICAL( F64 );
+                    PSIMAGE_CUT_VERTICAL( C32 );
+                    PSIMAGE_CUT_VERTICAL( C64 );
+                    default:
+                    psError( __func__, "Unsupported datatype (%d)", type );
+                    psFree( out );
+                    out = NULL;
+                }
+            psFree( imgVec );
+            psFree( maskVec );
+        } else if ( direction == PS_CUT_Y_POS || direction == PS_CUT_Y_NEG ) { // Cut in Y direction
+            psVector * imgVec = NULL;
+            psVector* maskVec = NULL;
+            int elementSize = PSELEMTYPE_SIZEOF( type );
+            
+            // fill in psVectors to fake out the statistics functions.
+            imgVec = psAlloc( sizeof( psVector ) );
+            imgVec->type = in->type;
+            imgVec->n = imgVec->nalloc = numCols;
+            if ( mask != NULL ) {
+                    maskVec = psAlloc( sizeof( psVector ) );
+                    maskVec->type = mask->type;
+                    maskVec->n = maskVec->nalloc = numCols;
+                }
+                
+            // recycle output to make a proper sized/type output structure
+            // n.b. type is double as that is the type given for all stats in psStats.
+            out = psVectorRecycle( out, PS_TYPE_F64, numRows );
+            outData = out->data.F64;
+            if ( delta < 0 ) {
+                    outData += numRows - 1;
+                }
+                
+            for ( int r = 0;r < numRows;r++ ) {
+                    // point the vector struct to the data to calculate the stats
+                    imgVec->data.V = ( void* ) ( in->data.U8[ row + r ] + col * elementSize );
+                    if ( maskVec != NULL ) {
+                            maskVec->data.V = ( void* ) ( mask->data.U8[ row + r ] + col * sizeof( psMaskType ) );
+                        }
+                    myStats = psVectorStats( myStats, imgVec, maskVec, maskVal );
+                    ( void ) p_psGetStatValue( myStats, &statVal ); // we know it works cause we tested it above
+                    *outData = statVal;
+                    outData += delta;
+                }
+            psFree( imgVec );
+            psFree( maskVec );
+        } else { // don't know what the direction flag is
+            psError( __func__, "Invalid direction flag (%d)", direction );
+            psFree( out );
             out = NULL;
         }
-        psFree(imgVec);
-        psFree(maskVec);
-    } else { // Cut in Y direction
-        psVector* imgVec = NULL;
-        psVector* maskVec = NULL;
-        int elementSize = PSELEMTYPE_SIZEOF(type);
-
-        // fill in psVectors to fake out the statistics functions.
-        imgVec = psAlloc(sizeof(psVector));
-        imgVec->type = in->type;
-        imgVec->n = imgVec->nalloc = numCols;
-        if (mask != NULL) {
-            maskVec = psAlloc(sizeof(psVector));
-            maskVec->type = mask->type;
-            maskVec->n = maskVec->nalloc = numCols;
-        }
-
-        // recycle output to make a proper sized/type output structure
-        // n.b. type is double as that is the type given for all stats in psStats.
-        out = psVectorRecycle(out,numRows,PS_TYPE_F64);
-        outData = out->data.F64;
-        if (delta < 0) {
-            outData += numCols - 1;
-        }
-
-        for (int r=0;r<numRows;r++) {
-            // point the vector struct to the data to calculate the stats
-            imgVec->data.V = (void*)(in->data.U8[row+r]+col*elementSize);
-            if (maskVec!=NULL) {
-                maskVec->data.V = (void*)(mask->data.U8[row+r]+col*sizeof(psMaskType));
-            }
-            myStats = psVectorStats(myStats,imgVec,maskVec,maskVal);
-            (void)p_psGetStatValue(myStats,&statVal); // we know it works cause we tested it above
-            *outData = statVal;
-            outData += delta;
-        }
-    }
-
+        
+    psFree( myStats );
+    
     return out;
 }
