public static void ConvolveAndTranspose(Kernel kernel, Color[] inPixels, Color[] outPixels, int width, int height, bool alpha, ConvolveWrapping edgeAction) { float[] matrix = kernel.Matrix; int cols = kernel.Columns; int cols2 = cols / 2; for (int y = 0; y < height; y++) { int index = y; int ioffset = y * width; for (int x = 0; x < width; x++) { float r = 0f; float g = 0f; float b = 0f; float a = 0f; int moffset = cols2; for (int col = -cols2; col <= cols2; col++) { float f = matrix[moffset + col]; if (f != 0) { int ix = x + col; if (ix < 0) { if (edgeAction == ConvolveWrapping.ClampEdges) { ix = 0; } else if (edgeAction == ConvolveWrapping.WrapEdges) { ix = (x + width) % width; } } else if (ix >= width) { if (edgeAction == ConvolveWrapping.ClampEdges) { ix = width - 1; } else if (edgeAction == ConvolveWrapping.WrapEdges) { ix = (x + width) % width; } } Color pixel = inPixels[ioffset + ix]; r += f * pixel.r; g += f * pixel.g; b += f * pixel.b; a += f * pixel.a; } } outPixels[index] = new Color(r, g, b, a); index += height; } } }
/// <summary>Convolve with a 2D kernel</summary> public static void ConvolveHV(Kernel kernel, Color[] inPixels, Color[] outPixels, int width, int height, bool alpha, ConvolveWrapping edgeAction) { int index = 0; float[] matrix = kernel.Matrix; int rows = kernel.Rows; int cols = kernel.Columns; int rows2 = rows / 2; int cols2 = cols / 2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0f; float g = 0f; float b = 0f; float a = 0f; for (int row = -rows2; row <= rows2; row++) { int iy = y + row; int ioffset; if (0 <= iy && iy < height) { ioffset = iy * width; } else if (edgeAction == ConvolveWrapping.ClampEdges) { ioffset = y * width; } else if (edgeAction == ConvolveWrapping.WrapEdges) { ioffset = ((iy + height) % height) * width; } else { continue; } int moffset = cols * (row + rows2) + cols2; for (int col = -cols2; col <= cols2; col++) { float f = matrix[moffset + col]; if (f != 0) { int ix = x + col; if (!(0 <= ix && ix < width)) { if (edgeAction == ConvolveWrapping.ClampEdges) { ix = x; } else if (edgeAction == ConvolveWrapping.WrapEdges) { ix = (x + width) % width; } else { continue; } } Color pixel = inPixels[ioffset + ix]; r += f * pixel.r; g += f * pixel.g; b += f * pixel.b; a += f * pixel.a; } } } outPixels[index++] = new Color(r, g, b, a); } } }
/// <summary>Convolve with a 2D kernel</summary> public static void Convolve(Kernel kernel, Color[] inPixels, Color[] outPixels, int width, int height, ConvolveWrapping edgeAction) { Convolve(kernel, inPixels, outPixels, width, height, true, edgeAction); }
/// <summary>Convolve with a 2D kernel</summary> public static void Convolve(Kernel kernel, Color[] inPixels, Color[] outPixels, int width, int height, bool alpha, ConvolveWrapping edgeAction) { if (kernel.Rows == 1) { ConvolveH(kernel, inPixels, outPixels, width, height, alpha, edgeAction); } else if (kernel.Columns == 1) { ConvolveV(kernel, inPixels, outPixels, width, height, alpha, edgeAction); } else { ConvolveHV(kernel, inPixels, outPixels, width, height, alpha, edgeAction); } }
/** * Convolve with a kernel consisting of one column */ public static void ConvolveV(Kernel kernel, Color[] inPixels, Color[] outPixels, int width, int height, bool alpha, ConvolveWrapping edgeAction) { int index = 0; float[] matrix = kernel.Matrix; int rows = kernel.Rows; int rows2 = rows / 2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0f; float g = 0f; float b = 0f; float a = 0f; for (int row = -rows2; row <= rows2; row++) { int iy = y + row; int ioffset; if (iy < 0) { switch (edgeAction) { case ConvolveWrapping.ClampEdges: ioffset = 0; break; case ConvolveWrapping.WrapEdges: ioffset = ((y + height) % height) * width; break; default: ioffset = iy * width; break; } } else if (iy >= height) { switch (edgeAction) { case ConvolveWrapping.ClampEdges: ioffset = (height - 1) * width; break; case ConvolveWrapping.WrapEdges: ioffset = ((y + height) % height) * width; break; default: ioffset = iy * width; break; } } else { ioffset = iy * width; } float f = matrix[row + rows2]; if (f != 0) { Color pixel = inPixels[ioffset + x]; r += f * pixel.r; g += f * pixel.g; b += f * pixel.b; a += f * pixel.a; } } outPixels[index++] = new Color(r, g, b, a); } } }