Index: /trunk/psLib/src/imageops/psImageConvolve.c
===================================================================
--- /trunk/psLib/src/imageops/psImageConvolve.c	(revision 32723)
+++ /trunk/psLib/src/imageops/psImageConvolve.c	(revision 32724)
@@ -765,4 +765,128 @@
 }
 
+// XXX NOTE : work to do : figure out the actual containers needed in there, pre-allocate them
+bool psImageSmooth_PreAlloc_F32(psImage *image, double sigma, double Nsigma)
+{
+    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
+    // assert on data type
+
+    // relevant terms
+    int Nrange = sigma*Nsigma + 0.5;    // Number of pixels either side for convolution kernel
+    int Nx = image->numCols;            // Number of columns
+    int Ny = image->numRows;            // Number of rows
+
+    IMAGE_SMOOTH_GAUSS(gaussnorm, Nrange, sigma, F32);
+    psF32 *gauss = &gaussnorm->data.F32[Nrange];
+       
+    // use a temp running buffer for X and Y directions.
+    psF32 *resultX = (psF32 *) psAlloc(Nx * sizeof(psF32));
+    memset (resultX, 0, Nx*sizeof(psF32));
+    psF32 *resultY = (psF32 *) psAlloc(Ny * sizeof(psF32));
+    memset (resultY, 0, Ny*sizeof(psF32));
+
+    /* Smooth in X direction */
+    {
+	for (int j = 0; j < Ny; j++) {
+	    psF32 *vi = image->data.F32[j];
+	    int xMax = PS_MIN(Nrange, Nx);
+	    int convRange = PS_MIN(Nrange + 1, Nx);
+	    /* Smooth first Nrange pixels, with renorm */
+	    for (int i = 0; i < xMax; i++, vi++) {
+		psF32 *vr = vi - i;
+		psF32 *vg = gauss - i;
+		double g = 0.0;
+		double s = 0.0;
+		for (int n = -i; n < convRange; n++, vr++, vg++) {
+		    s += *vg * *vr;
+		    g += *vg;
+		}
+		resultX[i] = s / g;
+	    }
+	    /* If that's all the pixels we have, then we're done already */
+	    if (Nx > Nrange) {
+		/* Smooth middle pixels */
+		for (int i = Nrange; i < Nx - Nrange; i++, vi++) {
+		    psF32 *vr = vi - Nrange;
+		    psF32 *vg = gauss - Nrange;
+		    double s = 0;
+		    for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) {
+			s += *vg * *vr;
+		    }
+		    resultX[i] = s;
+		}
+		/* Smooth last Nrange pixels, with renorm */
+		for (int i = Nx - Nrange; i < Nx; i++, vi++) {
+		    psF32 *vr = vi - Nrange;
+		    psF32 *vg = gauss - Nrange;
+		    double g = 0.0;
+		    double s = 0.0;
+		    for (int n = -Nrange; n < Nx - i; n++, vr++, vg++) {
+			s += *vg * *vr;
+			g += *vg;
+		    }
+		    resultX[i] = s / g;
+		}
+	    }
+	    memcpy(image->data.F32[j], resultX, Nx*sizeof(psF32));
+	}
+    }
+       
+    // this section probably hits the cache poorly for large images, but is probably OK for small ones
+    /* Smooth in Y direction */
+    {
+	for (int i = 0; i < Nx; i++) {
+	    int yMax = PS_MIN(Nrange, Ny);
+	    int convRange = PS_MIN(Nrange + 1, Ny);
+	    /* Smooth first Nrange pixels, with renorm */
+	    for (int j = 0; j < yMax; j++) {
+		psF32 *vg = gauss - j;
+		double g = 0.0;
+		double s = 0.0;
+		for (int n = -j; n < convRange; n++, vg++) {
+		    psF32 vr = image->data.F32[j+n][i];
+		    s += *vg * vr;
+		    g += *vg;
+		}
+		resultY[j] = s / g;
+	    }
+	    /* If that's all the pixels we have, then we're done already */
+	    if (Ny > Nrange) {
+		/* Smooth middle pixels */
+		for (int j = Nrange; j < Ny - Nrange; j++) {
+		    psF32 *vg = gauss - Nrange;
+		    double s = 0;
+		    for (int n = -Nrange; n < Nrange + 1; n++, vg++) {
+			psF32 vr = image->data.F32[j+n][i]; 
+			s += *vg * vr;
+		    }
+		    resultY[j] = s;
+		}
+		/* Smooth last Nrange pixels, with renorm */
+		for (int j = Ny - Nrange; j < Ny; j++) {
+		    psF32 *vg = gauss - Nrange;
+		    double g = 0.0;
+		    double s = 0.0;
+		    for (int n = -Nrange; n < Ny - j; n++, vg++) {
+			psF32 vr = image->data.F32[j+n][i];
+			s += *vg * vr;
+			g += *vg;
+		    }
+		    resultY[j] = s / g;
+		}
+	    }
+	    // loop here 
+	    for (int j = 0; j < Ny; j++) {
+		image->data.F32[j][i] = resultY[j];
+	    }
+	}
+    }
+       
+    psFree(resultX);
+    psFree(resultY);
+    psFree(gaussnorm);
+
+    return true;
+}
+
 static bool imageSmoothMaskPixels(psVector *out, const psImage *image, const psImage *mask,
                                   psImageMaskType maskVal, const psVector *x, const psVector *y,
