Index: trunk/psLib/src/imageops/psImageGeomManip.c
===================================================================
--- trunk/psLib/src/imageops/psImageGeomManip.c	(revision 4211)
+++ trunk/psLib/src/imageops/psImageGeomManip.c	(revision 4214)
@@ -10,6 +10,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-06-10 21:26:47 $
+ *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-06-11 02:19:05 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -688,9 +688,6 @@
 }
 
-
-// XXX: implementation is awaiting working psPlaneTransform functions like
-// invert.  Also, the next SDRS should have a different signature.
 psImage* psImageTransform(psImage *output,
-                          psArray** blankPixels,
+                          psPixels* blankPixels,
                           const psImage *input,
                           const psImage *inputMask,
@@ -705,5 +702,27 @@
         psError(PS_ERR_BAD_PARAMETER_NULL, true,
                 PS_ERRORTEXT_psImage_IMAGE_NULL);
-        return NULL;
+        psFree(output);
+        return NULL;
+    }
+    psElemType type = input->type.type;
+
+    if (inputMask != NULL) {
+        if (input->numRows != inputMask->numRows || input->numCols != inputMask->numCols) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    PS_ERRORTEXT_psImage_IMAGE_MASK_SIZE,
+                    input->numCols, input->numRows,
+                    inputMask->numCols, inputMask->numRows );
+            psFree(output);
+            return NULL;
+        }
+        if (inputMask->type.type != PS_TYPE_MASK) {
+            char* typeStr;
+            PS_TYPE_NAME(typeStr,inputMask->type.type);
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                    PS_ERRORTEXT_psImage_IMAGE_MASK_TYPE,
+                    typeStr, PS_TYPE_MASK_NAME);
+            psFree(output);
+            return NULL;
+        }
     }
 
@@ -714,31 +733,44 @@
     }
 
-    int row0 = region.y0;
-    int row1 = region.y1;
-    int col0 = region.x0;
-    int col1 = region.x1;
-    if (col1 < 1) {
-        col1 += input->numCols;
-    }
-
-    if (row1 < 1) {
-        row1 += input->numRows;
-    }
-
-    int numRows = row1 - row0;
-    int numCols = col1 - col0;
-
-    if (numRows < 1 || numCols < 1) {
-        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
-                "The specified region is invalid.");
-        psFree(output);
-        return NULL;
-    }
-
-    // create the output image.
-    output = psImageRecycle(output, numCols, numRows, input->type.type);
-    *(psS32*)&output->col0 = region.x0;
-    *(psS32*)&output->row0 = region.y0;
-
+    int row0;
+    int row1;
+    int col0;
+    int col1;
+    int numRows;
+    int numCols;
+    if (output == NULL) { // output image size is determined by psRegion
+        row0 = region.y0;
+        row1 = region.y1;
+        col0 = region.x0;
+        col1 = region.x1;
+        if (col1 < 1) {
+            col1 += input->numCols;
+        }
+
+        if (row1 < 1) {
+            row1 += input->numRows;
+        }
+
+        numRows = row1 - row0;
+        numCols = col1 - col0;
+
+        if (numRows < 1 || numCols < 1) {
+            psError(PS_ERR_BAD_PARAMETER_SIZE, true,
+                    "The specified region is invalid.");
+            psFree(output);
+            return NULL;
+        }
+        // create the output image.
+        output = psImageRecycle(output, numCols, numRows, input->type.type);
+        *(psS32*)&output->col0 = region.x0;
+        *(psS32*)&output->row0 = region.y0;
+    } else { // size of output is determined by output parameter
+        numRows = output->numRows;
+        numCols = output->numCols;
+        row0 = output->row0;
+        col0 = output->col0;
+        row1 = row0+numRows;
+        col1 = col0+numCols;
+    }
 
     // loop through the output image using the domain above and transform
@@ -747,25 +779,83 @@
     psPlane outPosition;
     psPlane* inPosition = NULL;
-    for (int row = 0; row < numRows; row++) {
-        outPosition.y = row+row0;
-        psF32* outputData=output->data.F32[row];
-        for (int col = 0; col < numCols; col++) {
-            outPosition.x = col+col0;
-            // apply the transform to get the position in the input image
-            inPosition = psPlaneTransformApply(inPosition, outToIn, &outPosition);
-
-            if (inPosition == NULL) {
-                psError(PS_ERR_UNKNOWN, false,
-                        "Failed to apply the transform");
-                psFree(output);
-                return NULL;
-            }
-            // interpolate the cooresponding input pixel to get the output pixel value.
-            outputData[col] = (psF32)psImagePixelInterpolate(input,
-                              inPosition->x, inPosition->y,
-                              inputMask, inputMaskVal, exposedValue,
-                              mode);
-
-        }
+
+    #define PSIMAGE_TRANSFORM_DOTRANSFORM(TYPE,MODE) \
+    /* apply the transform to get the position in the input image */ \
+    inPosition = psPlaneTransformApply(inPosition, outToIn, &outPosition); \
+    \
+    if (inPosition == NULL) { \
+        psError(PS_ERR_UNKNOWN, false, \
+                "Failed to apply the transform"); \
+        psFree(output); \
+        return NULL; \
+    } \
+    /* interpolate the cooresponding input pixel to get the output pixel value. */ \
+    ps##TYPE value = p_psImagePixelInterpolate##MODE##_##TYPE(input, \
+                     inPosition->x, inPosition->y, \
+                     inputMask, inputMaskVal, NAN); \
+    if (isnan(value)) { \
+        if (blankPixels != NULL) { \
+            p_psPixelsAppend(blankPixels, blankPixels->nalloc, outPosition.x, outPosition.y); \
+        } \
+        value = exposedValue; \
+    } \
+
+    #define PSIMAGE_TRANSFORM_LOOP(TYPE, MODE) { \
+        for (int row = 0; row < numRows; row++) { \
+            outPosition.y = row+row0; \
+            ps##TYPE* outputData=output->data.TYPE[row]; \
+            for (int col = 0; col < numCols; col++) { \
+                outPosition.x = col+col0; \
+                PSIMAGE_TRANSFORM_DOTRANSFORM(TYPE,MODE) \
+                outputData[col] = value; \
+            } \
+        } \
+    }
+
+    #define PSIMAGE_TRANSFORM_FROMLIST(TYPE, MODE) { \
+        int n = pixels->n; \
+        for (int i= 0; i < n; i++) { \
+            int x = pixels->data[i].x; \
+            int y = pixels->data[i].y; \
+            if (x >= col0 && x < col1 && y >= row0 && y < row1) { \
+                outPosition.x = x; \
+                outPosition.y = y; \
+                PSIMAGE_TRANSFORM_DOTRANSFORM(TYPE,MODE) \
+                output->data.TYPE[y][x] = value; \
+            } \
+        } \
+    }
+
+    #define PSIMAGE_TRANSFORM_CASE(MODE) \
+case PS_INTERPOLATE_##MODE: \
+    switch (type) { \
+    case PS_TYPE_F32: \
+        PSIMAGE_TRANSFORM_LOOP(F32,MODE); \
+        break; \
+    case PS_TYPE_F64: \
+        PSIMAGE_TRANSFORM_LOOP(F64,MODE); \
+        break; \
+    default: { \
+            char* typeStr; \
+            PS_TYPE_NAME(typeStr,type); \
+            psError(PS_ERR_BAD_PARAMETER_TYPE, true, \
+                    PS_ERRORTEXT_psImage_IMAGE_TYPE_UNSUPPORTED, \
+                    typeStr); \
+            psFree(output); \
+            return NULL; \
+        } \
+    } \
+    break;
+
+    switch (mode) {
+        PSIMAGE_TRANSFORM_CASE(FLAT);
+        PSIMAGE_TRANSFORM_CASE(BILINEAR);
+        PSIMAGE_TRANSFORM_CASE(BILINEAR_VARIANCE);
+    default:
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                PS_ERRORTEXT_psImageManip_INTERPOLATION_MODE_UNSUPPORTED,
+                mode);
+        psFree(output);
+        return NULL;
     }
 
