// Apply a Gaussian filter of size filtersz - separable implementation private MultiDimFloatTexture applyGaussianFilter_Separable(int filtersz) { // . compute Gauss kernel MultiDimFloatTexture kernel = new MultiDimFloatTexture(filtersz, 1, 1); float sum = 0; for (int i = 0; i < filtersz; i++) { float di = (float)(i - filtersz / 2); float u2 = (di * di) / ((float)filtersz * filtersz); float sigma = 1.0f / 3.0f; // > 3 std dev => assume 0 kernel.set((float)Math.Exp(-u2 / (2.0f * sigma * sigma)), i, 0, 0); sum += kernel.get(i, 0, 0); } // . normalize for (int i = 0; i < filtersz; i++) { kernel.set(kernel.get(i, 0, 0) / sum, i, 0, 0); } // . alloc result and tmp buffer (initialized to 0) MultiDimFloatTexture tmp = new MultiDimFloatTexture(m_iW, m_iH, m_iNumComp); MultiDimFloatTexture res = new MultiDimFloatTexture(m_iW, m_iH, m_iNumComp); // . convolve - pass 1 (treat texture as toroidal) for (int v = 0; v < m_iH; v++) { for (int u = 0; u < m_iW; u++) { for (int i = 0; i < filtersz; i++) { int x = u + i - filtersz / 2; int y = v; for (int c = 0; c < numComp(); c++) { float val = tmp.get(u, v, c); tmp.set(val + ((float)getmod(x, y, c)) * kernel.get(i, 0, 0), u, v, c); } } } } // . convolve - pass 2 (treat texture as toroidal) for (int v = 0; v < m_iH; v++) { for (int u = 0; u < m_iW; u++) { for (int j = 0; j < filtersz; j++) { int x = u; int y = v + j - filtersz / 2; for (int c = 0; c < m_iNumComp; c++) { float val = res.get(u, v, c); res.set(val + ((float)tmp.getmod(x, y, c)) * kernel.get(j, 0, 0), u, v, c); } } } } kernel = null; tmp = null; return(res); }