Index: /trunk/psLib/src/image/psImage.h
===================================================================
--- /trunk/psLib/src/image/psImage.h	(revision 1935)
+++ /trunk/psLib/src/image/psImage.h	(revision 1936)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-28 23:26:48 $
+ *  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-30 21:01:09 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -52,18 +52,18 @@
 
     union {
-        psU8* *U8;                     ///< Unsigned 8-bit integer data.
-        psU16* *U16;                   ///< Unsigned 16-bit integer data.
-        psU32* *U32;                   ///< Unsigned 32-bit integer data.
-        psU64* *U64;                   ///< Unsigned 64-bit integer data.
-        psS8* *S8;                     ///< Signed 8-bit integer data.
-        psS16* *S16;                   ///< Signed 16-bit integer data.
-        psS32* *S32;                   ///< Signed 32-bit integer data.
-        psS64* *S64;                   ///< Signed 64-bit integer data.
-        psF32* *F32;                   ///< Single-precision float data.
-        psF64* *F64;                   ///< Double-precision float data.
-        psC32* *C32;                   ///< Single-precision complex data.
-        psC64* *C64;                   ///< Double-precision complex data.
-        psPTR* *PTR;                   ///< Void pointers.
-        psPTR* V;                      ///< Pointer to data.
+        psU8**  U8;                    ///< Unsigned 8-bit integer data.
+        psU16** U16;                   ///< Unsigned 16-bit integer data.
+        psU32** U32;                   ///< Unsigned 32-bit integer data.
+        psU64** U64;                   ///< Unsigned 64-bit integer data.
+        psS8**  S8;                    ///< Signed 8-bit integer data.
+        psS16** S16;                   ///< Signed 16-bit integer data.
+        psS32** S32;                   ///< Signed 32-bit integer data.
+        psS64** S64;                   ///< Signed 64-bit integer data.
+        psF32** F32;                   ///< Single-precision float data.
+        psF64** F64;                   ///< Double-precision float data.
+        psC32** C32;                   ///< Single-precision complex data.
+        psC64** C64;                   ///< Double-precision complex data.
+        psPTR** PTR;                   ///< Void pointers.
+        psPTR*  V;                     ///< Pointer to data.
     } data;                            ///< Union for data types.
     const struct psImage* parent;      ///< Parent, if a subimage.
Index: /trunk/psLib/src/image/psImageConvolve.c
===================================================================
--- /trunk/psLib/src/image/psImageConvolve.c	(revision 1935)
+++ /trunk/psLib/src/image/psImageConvolve.c	(revision 1936)
@@ -5,6 +5,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-23 18:30:57 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-30 21:01:09 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -15,4 +15,5 @@
 #include "psImageConvolve.h"
 #include "psImageFFT.h"
+#include "psImageExtraction.h"
 #include "psMatrixVectorArithmetic.h"
 #include "psMemory.h"
@@ -21,4 +22,6 @@
 
 #include "psImageErrors.h"
+
+#define FOURIER_PADDING 32 /* padding amount in every side of the image for fourier convolution */
 
 static void freeKernel(psKernel* ptr);
@@ -32,22 +35,22 @@
     // following is explicitly spelled out in the SDRS as a requirement
     if (yMin > yMax) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
+                 yMin, yMax);
+
         int temp = yMin;
         yMin = yMax;
         yMax = temp;
-
-        psLogMsg(__func__, PS_LOG_WARN,
-                 "Found yMin > yMax (%d > %d).  Values swapped.",
-                 yMin, yMax);
     }
 
     // following is explicitly spelled out in the SDRS as a requirement
     if (xMin > xMax) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
+                 xMin, xMax);
+
         int temp = xMin;
         xMin = xMax;
         xMax = temp;
-
-        psLogMsg(__func__, PS_LOG_WARN,
-                 "Found xMin > xMax (%d > %d).  Values swapped.",
-                 xMin, xMax);
     }
 
@@ -295,11 +298,12 @@
     } else {
         // fourier convolution
+        int paddedCols = numCols+2*FOURIER_PADDING;
+        int paddedRows = numRows+2*FOURIER_PADDING;
+
+        // check to see if kernel is smaller, otherwise padding it up will fail.
         int kRows = kernel->image->numRows;
         int kCols = kernel->image->numCols;
-        int x0 = (numCols - kCols) / 2;
-        int y0 = (numRows - kRows) / 2;
-        psImage* paddedKernel;
-
-        // check to see if kernel is smaller, otherwise padding it up will fail.
+        int x0 = (paddedCols - kCols) / 2;
+        int y0 = (paddedRows - kRows) / 2;
         if (x0 < 0 || y0 < 0) {
             psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve",
@@ -312,7 +316,30 @@
         }
 
-        // pad the kernel to the same size of image
-        paddedKernel = psImageAlloc(numCols,numRows,PS_TYPE_KERNEL);
-        memset(paddedKernel->data.V,0,sizeof(psKernelType)*numCols*numRows); // zeroize image
+        // pad the image
+        psImage* paddedImage = psImageAlloc(paddedCols,paddedRows,in->type.type);
+        int elementSize = PSELEMTYPE_SIZEOF(in->type.type);
+
+        // zero out padded area on top and bottom
+        memset(paddedImage->data.U8[0],0,FOURIER_PADDING*paddedCols*elementSize);
+        memset(paddedImage->data.U8[FOURIER_PADDING+numRows-1],0,FOURIER_PADDING*paddedCols*elementSize);
+
+        // fill in the image-containing rows.
+        int sidePaddingSize = FOURIER_PADDING*elementSize;
+        int imageRowSize = numCols*elementSize;
+        psU8* paddedData = paddedImage->data.U8[FOURIER_PADDING];
+        for (int row=0;row<numRows;row++) {
+            // zero out padded area on left edge.
+            memset(paddedData,0,sidePaddingSize);
+            paddedData += sidePaddingSize;
+            memcpy(paddedData,in->data.U8[row],imageRowSize);
+            paddedData += imageRowSize;
+            // zero out padded area on right edge.
+            memset(paddedData,0,sidePaddingSize);
+            paddedData += sidePaddingSize;
+        }
+
+        // pad the kernel to the same size of paddedImage
+        psImage* paddedKernel = psImageAlloc(paddedCols,paddedRows,PS_TYPE_KERNEL);
+        memset(paddedKernel->data.U8[0],0,sizeof(psKernelType)*numCols*numRows); // zero-out image
         for (int row=0;row<kRows;row++) {
             psKernelType* padRow = paddedKernel->data.PS_TYPE_KERNEL_DATA[row+y0];
@@ -332,6 +359,5 @@
         }
 
-
-        psImage* inFourier = psImageFFT(NULL, in, PS_FFT_FORWARD);
+        psImage* inFourier = psImageFFT(NULL, paddedImage, PS_FFT_FORWARD);
         if (inFourier == NULL) {
             psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve",
@@ -343,5 +369,5 @@
 
         // convolution in fourier domain is just a pixel-wise multiplication
-        psImage* outFourier = psImageAlloc(numCols,numRows,inFourier->type.type);
+        psImage* outFourier = psImageAlloc(paddedCols,paddedRows,inFourier->type.type);
         psBinaryOp(outFourier,inFourier,"*",kernelFourier);
 
@@ -355,10 +381,16 @@
         }
 
-        // since our image was real to start, the result is real
-        out = psImageReal(out,complexOut);
-
-        psFree(complexOut);
+        // subset out the padded area now.
+        psImage* complexOutSansPad = psImageSubset(complexOut,
+                                     FOURIER_PADDING,FOURIER_PADDING,
+                                     FOURIER_PADDING+numCols,FOURIER_PADDING+numRows);
+
+        // since our image was real, the result is to be real as well
+        out = psImageReal(out,complexOutSansPad);
+
+        psFree(complexOut); // frees complexOutSansPad, as it is a child.
         psFree(kernelFourier);
         psFree(inFourier);
+        psFree(paddedImage);
         psFree(paddedKernel);
 
Index: /trunk/psLib/src/imageops/psImageConvolve.c
===================================================================
--- /trunk/psLib/src/imageops/psImageConvolve.c	(revision 1935)
+++ /trunk/psLib/src/imageops/psImageConvolve.c	(revision 1936)
@@ -5,6 +5,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-23 18:30:57 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-30 21:01:09 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -15,4 +15,5 @@
 #include "psImageConvolve.h"
 #include "psImageFFT.h"
+#include "psImageExtraction.h"
 #include "psMatrixVectorArithmetic.h"
 #include "psMemory.h"
@@ -21,4 +22,6 @@
 
 #include "psImageErrors.h"
+
+#define FOURIER_PADDING 32 /* padding amount in every side of the image for fourier convolution */
 
 static void freeKernel(psKernel* ptr);
@@ -32,22 +35,22 @@
     // following is explicitly spelled out in the SDRS as a requirement
     if (yMin > yMax) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "Specified yMin, %d, was greater than yMax, %d.  Values swapped.",
+                 yMin, yMax);
+
         int temp = yMin;
         yMin = yMax;
         yMax = temp;
-
-        psLogMsg(__func__, PS_LOG_WARN,
-                 "Found yMin > yMax (%d > %d).  Values swapped.",
-                 yMin, yMax);
     }
 
     // following is explicitly spelled out in the SDRS as a requirement
     if (xMin > xMax) {
+        psLogMsg(__func__, PS_LOG_WARN,
+                 "Specified xMin, %d, was greater than xMax, %d.  Values swapped.",
+                 xMin, xMax);
+
         int temp = xMin;
         xMin = xMax;
         xMax = temp;
-
-        psLogMsg(__func__, PS_LOG_WARN,
-                 "Found xMin > xMax (%d > %d).  Values swapped.",
-                 xMin, xMax);
     }
 
@@ -295,11 +298,12 @@
     } else {
         // fourier convolution
+        int paddedCols = numCols+2*FOURIER_PADDING;
+        int paddedRows = numRows+2*FOURIER_PADDING;
+
+        // check to see if kernel is smaller, otherwise padding it up will fail.
         int kRows = kernel->image->numRows;
         int kCols = kernel->image->numCols;
-        int x0 = (numCols - kCols) / 2;
-        int y0 = (numRows - kRows) / 2;
-        psImage* paddedKernel;
-
-        // check to see if kernel is smaller, otherwise padding it up will fail.
+        int x0 = (paddedCols - kCols) / 2;
+        int y0 = (paddedRows - kRows) / 2;
         if (x0 < 0 || y0 < 0) {
             psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve",
@@ -312,7 +316,30 @@
         }
 
-        // pad the kernel to the same size of image
-        paddedKernel = psImageAlloc(numCols,numRows,PS_TYPE_KERNEL);
-        memset(paddedKernel->data.V,0,sizeof(psKernelType)*numCols*numRows); // zeroize image
+        // pad the image
+        psImage* paddedImage = psImageAlloc(paddedCols,paddedRows,in->type.type);
+        int elementSize = PSELEMTYPE_SIZEOF(in->type.type);
+
+        // zero out padded area on top and bottom
+        memset(paddedImage->data.U8[0],0,FOURIER_PADDING*paddedCols*elementSize);
+        memset(paddedImage->data.U8[FOURIER_PADDING+numRows-1],0,FOURIER_PADDING*paddedCols*elementSize);
+
+        // fill in the image-containing rows.
+        int sidePaddingSize = FOURIER_PADDING*elementSize;
+        int imageRowSize = numCols*elementSize;
+        psU8* paddedData = paddedImage->data.U8[FOURIER_PADDING];
+        for (int row=0;row<numRows;row++) {
+            // zero out padded area on left edge.
+            memset(paddedData,0,sidePaddingSize);
+            paddedData += sidePaddingSize;
+            memcpy(paddedData,in->data.U8[row],imageRowSize);
+            paddedData += imageRowSize;
+            // zero out padded area on right edge.
+            memset(paddedData,0,sidePaddingSize);
+            paddedData += sidePaddingSize;
+        }
+
+        // pad the kernel to the same size of paddedImage
+        psImage* paddedKernel = psImageAlloc(paddedCols,paddedRows,PS_TYPE_KERNEL);
+        memset(paddedKernel->data.U8[0],0,sizeof(psKernelType)*numCols*numRows); // zero-out image
         for (int row=0;row<kRows;row++) {
             psKernelType* padRow = paddedKernel->data.PS_TYPE_KERNEL_DATA[row+y0];
@@ -332,6 +359,5 @@
         }
 
-
-        psImage* inFourier = psImageFFT(NULL, in, PS_FFT_FORWARD);
+        psImage* inFourier = psImageFFT(NULL, paddedImage, PS_FFT_FORWARD);
         if (inFourier == NULL) {
             psErrorMsg(PS_ERRORNAME_DOMAIN "psImageConvolve",
@@ -343,5 +369,5 @@
 
         // convolution in fourier domain is just a pixel-wise multiplication
-        psImage* outFourier = psImageAlloc(numCols,numRows,inFourier->type.type);
+        psImage* outFourier = psImageAlloc(paddedCols,paddedRows,inFourier->type.type);
         psBinaryOp(outFourier,inFourier,"*",kernelFourier);
 
@@ -355,10 +381,16 @@
         }
 
-        // since our image was real to start, the result is real
-        out = psImageReal(out,complexOut);
-
-        psFree(complexOut);
+        // subset out the padded area now.
+        psImage* complexOutSansPad = psImageSubset(complexOut,
+                                     FOURIER_PADDING,FOURIER_PADDING,
+                                     FOURIER_PADDING+numCols,FOURIER_PADDING+numRows);
+
+        // since our image was real, the result is to be real as well
+        out = psImageReal(out,complexOutSansPad);
+
+        psFree(complexOut); // frees complexOutSansPad, as it is a child.
         psFree(kernelFourier);
         psFree(inFourier);
+        psFree(paddedImage);
         psFree(paddedKernel);
 
Index: /trunk/psLib/src/mathtypes/psImage.h
===================================================================
--- /trunk/psLib/src/mathtypes/psImage.h	(revision 1935)
+++ /trunk/psLib/src/mathtypes/psImage.h	(revision 1936)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-28 23:26:48 $
+ *  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-30 21:01:09 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -52,18 +52,18 @@
 
     union {
-        psU8* *U8;                     ///< Unsigned 8-bit integer data.
-        psU16* *U16;                   ///< Unsigned 16-bit integer data.
-        psU32* *U32;                   ///< Unsigned 32-bit integer data.
-        psU64* *U64;                   ///< Unsigned 64-bit integer data.
-        psS8* *S8;                     ///< Signed 8-bit integer data.
-        psS16* *S16;                   ///< Signed 16-bit integer data.
-        psS32* *S32;                   ///< Signed 32-bit integer data.
-        psS64* *S64;                   ///< Signed 64-bit integer data.
-        psF32* *F32;                   ///< Single-precision float data.
-        psF64* *F64;                   ///< Double-precision float data.
-        psC32* *C32;                   ///< Single-precision complex data.
-        psC64* *C64;                   ///< Double-precision complex data.
-        psPTR* *PTR;                   ///< Void pointers.
-        psPTR* V;                      ///< Pointer to data.
+        psU8**  U8;                    ///< Unsigned 8-bit integer data.
+        psU16** U16;                   ///< Unsigned 16-bit integer data.
+        psU32** U32;                   ///< Unsigned 32-bit integer data.
+        psU64** U64;                   ///< Unsigned 64-bit integer data.
+        psS8**  S8;                    ///< Signed 8-bit integer data.
+        psS16** S16;                   ///< Signed 16-bit integer data.
+        psS32** S32;                   ///< Signed 32-bit integer data.
+        psS64** S64;                   ///< Signed 64-bit integer data.
+        psF32** F32;                   ///< Single-precision float data.
+        psF64** F64;                   ///< Double-precision float data.
+        psC32** C32;                   ///< Single-precision complex data.
+        psC64** C64;                   ///< Double-precision complex data.
+        psPTR** PTR;                   ///< Void pointers.
+        psPTR*  V;                     ///< Pointer to data.
     } data;                            ///< Union for data types.
     const struct psImage* parent;      ///< Parent, if a subimage.
Index: /trunk/psLib/src/pslib.h
===================================================================
--- /trunk/psLib/src/pslib.h	(revision 1935)
+++ /trunk/psLib/src/pslib.h	(revision 1936)
@@ -9,6 +9,6 @@
 *  @author Eric Van Alst, MHPCC
 *
-*  @version $Revision: 1.23 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-09-14 01:32:52 $
+*  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-09-30 21:01:09 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -88,4 +88,5 @@
 #include "psImageExtraction.h"
 #include "psImageManip.h"
+#include "psImageConvolve.h"
 
 /// @defgroup ImageIO Image File I/O Functions
Index: /trunk/psLib/test/image/Makefile
===================================================================
--- /trunk/psLib/test/image/Makefile	(revision 1935)
+++ /trunk/psLib/test/image/Makefile	(revision 1936)
@@ -3,6 +3,6 @@
 ##  Makefile:   test/collections
 ##
-##  $Revision: 1.2 $  $Name: not supported by cvs2svn $
-##  $Date: 2004-07-31 02:27:16 $
+##  $Revision: 1.3 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-09-30 21:01:09 $
 ##
 ##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -26,5 +26,6 @@
 tst_psImageStats02 \
 tst_psImageStats03 \
-tst_psImageExtraction
+tst_psImageExtraction \
+tst_psImageConvolve
 
 OBJS = $(addsuffix .o,$(TARGET))
Index: /trunk/psLib/test/image/tst_psImageConvolve.c
===================================================================
--- /trunk/psLib/test/image/tst_psImageConvolve.c	(revision 1936)
+++ /trunk/psLib/test/image/tst_psImageConvolve.c	(revision 1936)
@@ -0,0 +1,112 @@
+/** @file  tst_psImage.c
+ *
+ *  @brief Contains the tests for psImage.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-30 21:01:09 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "psTest.h"
+#include "pslib.h"
+#include "psType.h"
+
+static int testKernelAlloc(void);
+
+testDescription tests[] = {
+                              {testKernelAlloc,731,"psKernelAlloc",0,false},
+                              {NULL}
+                          };
+
+int main(int argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+
+    return ! runTestSuite(stderr,"psImage",tests,argc,argv);
+}
+
+static int testKernelAlloc(void)
+{
+    int numCases = 4;
+    int xMin[] = { -5,  0,-10,  5};
+    int xMax[] = {  0,  5, -5, 10};
+    int yMin[] = { -4,  0, -8,  4};
+    int yMax[] = {  0,  4, -4,  8};
+    int i;
+    psKernel* k;
+
+    for (i=0;i<numCases;i++) {
+        k = psKernelAlloc(xMin[i],xMax[i],yMin[i],yMax[i]);
+
+        if (k == NULL) {
+            psError(__func__,"psKernelAlloc returned NULL for [%d:%d,%d:%d].",
+                    xMin[i], xMax[i], yMin[i], yMax[i]);
+            return i*10+1;
+        }
+
+        if (k->xMin != xMin[i] || k->xMax != xMax[i] ||
+                k->yMin != yMin[i] || k->yMax != yMax[i]) {
+            psError(__func__,"Min/max members, [%d:%d,%d:%d], of psKernel wrong. Should be [%d:%d,%d:%d].",
+                    k->xMin,k->xMax, k->yMin, k->yMax,
+                    xMin[i], xMax[i], yMin[i], yMax[i]);
+            return i*10+2;
+        }
+
+        if (k->image->numCols != xMax[i]-xMin[i]+1 ||
+                k->image->numRows != yMax[i]-yMin[i]+1) {
+            psError(__func__,"Size of the kernel image is wrong (%dx%d vs %dx%d).",
+                    xMax[i]-xMin[i]+1, yMax[i]-yMin[i]+1,
+                    k->image->numCols, k->image->numRows);
+            return i*10+2;
+        }
+
+        for (int j=yMin[i]; j<yMax[i]; j++) {
+            if (k->kernel[j]+xMin[i] != k->image->data.PS_TYPE_KERNEL_DATA[j-yMin[i]]) {
+                psError(__func__,"The kernel pointer was set wrong for row %d.",
+                        j);
+                return i*10+4;
+            }
+        }
+
+        psFree(k);
+    }
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a warning (xMin > xMax)");
+    k = psKernelAlloc(5, -5, -2, 2);
+    if (k == NULL) {
+        psError(__func__,"psKernelAlloc returned NULL for xMin > xMax.");
+        return i*10+5;
+    }
+
+    if (k->xMin != -5 || k->xMax != 5) {
+        psError(__func__,"psKernelAlloc didn't swap xMin & xMax.");
+        return i*10+6;
+    }
+
+    psFree(k);
+
+    psLogMsg(__func__,PS_LOG_INFO,"Following should be a warning (yMin > yMax)");
+    k = psKernelAlloc(-2, 2, 5, -5);
+    if (k == NULL) {
+        psError(__func__,"psKernelAlloc returned NULL for yMin > yMax.");
+        return i*10+7;
+    }
+
+    if (k->yMin != -5 || k->yMax != 5) {
+        psError(__func__,"psKernelAlloc didn't swap yMin & yMax.");
+        return i*10+8;
+    }
+
+    psFree(k);
+
+    return 0;
+}
