/// <summary> /// Blur and transpose a block of ARGB pixels. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="premultiply"></param> /// <param name="unpremultiply"></param> /// <param name="edgeAction"></param> public static void ConvolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, bool premultiply, bool unpremultiply, EdgeMode edgeAction) { float[] matrix = kernel.GetKernel(); int cols = kernel.Width; 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 = 0, g = 0, b = 0, a = 0; 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 == EdgeMode.Clamp) ix = 0; else if (edgeAction == EdgeMode.Wrap) ix = (x + width)%width; } else if (ix >= width) { if (edgeAction == EdgeMode.Clamp) ix = width - 1; else if (edgeAction == EdgeMode.Wrap) ix = (x + width)%width; } int rgb = inPixels[ioffset + ix]; int pa = (rgb >> 24) & 0xff; int pr = (rgb >> 16) & 0xff; int pg = (rgb >> 8) & 0xff; int pb = rgb & 0xff; if (premultiply) { float a255 = pa*(1.0f/255.0f); pr = (int)(pr*a255); pg = (int)(pg*a255); pb = (int)(pb*a255); } a += f*pa; r += f*pr; g += f*pg; b += f*pb; } } if (unpremultiply && a != 0 && a != 255) { float f = 255.0f/a; r *= f; g *= f; b *= f; } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index] = (ia << 24) | (ir << 16) | (ig << 8) | ib; index += height; } } }
/// <summary> /// Convolve with a kernel consisting of one row. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="edgeAction"></param> public static void ConvolveH(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction) { int index = 0; float[] matrix = kernel.GetKernel(); int cols = kernel.Width; int cols2 = cols / 2; for (int y = 0; y < height; y++) { int ioffset = y * width; for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; 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 == EdgeMode.Clamp) { ix = 0; } else if (edgeAction == EdgeMode.Wrap) { ix = (x + width) % width; } } else if (ix >= width) { if (edgeAction == EdgeMode.Clamp) { ix = width - 1; } else if (edgeAction == EdgeMode.Wrap) { ix = (x + width) % width; } } int rgb = inPixels[ioffset + ix]; a += f * ((rgb >> 24) & 0xff); r += f * ((rgb >> 16) & 0xff); g += f * ((rgb >> 8) & 0xff); b += f * (rgb & 0xff); } } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } }
/// <summary> /// Convolve with a kernel consisting of one column. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="edgeAction"></param> public static void ConvolveV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction) { int index = 0; float[] matrix = kernel.GetKernel(); int rows = kernel.Height; int rows2 = rows/2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; for (int row = -rows2; row <= rows2; row++) { int iy = y + row; int ioffset; if (iy < 0) { if (edgeAction == EdgeMode.Clamp) ioffset = 0; else if (edgeAction == EdgeMode.Wrap) ioffset = ((y + height)%height)*width; else ioffset = iy*width; } else if (iy >= height) { if (edgeAction == EdgeMode.Clamp) ioffset = (height - 1)*width; else if (edgeAction == EdgeMode.Wrap) ioffset = ((y + height)%height)*width; else ioffset = iy*width; } else ioffset = iy*width; float f = matrix[row + rows2]; if (f != 0) { int rgb = inPixels[ioffset + x]; a += f*((rgb >> 24) & 0xff); r += f*((rgb >> 16) & 0xff); g += f*((rgb >> 8) & 0xff); b += f*(rgb & 0xff); } } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } }
/// <summary> /// Convolve with a kernel consisting of one row. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="edgeAction"></param> public static void ConvolveH(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction) { int index = 0; float[] matrix = kernel.GetKernel(); int cols = kernel.Width; int cols2 = cols/2; for (int y = 0; y < height; y++) { int ioffset = y*width; for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; 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 == EdgeMode.Clamp) ix = 0; else if (edgeAction == EdgeMode.Wrap) ix = (x + width)%width; } else if (ix >= width) { if (edgeAction == EdgeMode.Clamp) ix = width - 1; else if (edgeAction == EdgeMode.Wrap) ix = (x + width)%width; } int rgb = inPixels[ioffset + ix]; a += f*((rgb >> 24) & 0xff); r += f*((rgb >> 16) & 0xff); g += f*((rgb >> 8) & 0xff); b += f*(rgb & 0xff); } } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } }
/// <summary> /// Convolve with a 2D kernel. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="edgeAction"></param> public static void ConvolveHV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction) { int index = 0; float[] matrix = kernel.GetKernel(); int rows = kernel.Height; int cols = kernel.Width; int rows2 = rows/2; int cols2 = cols/2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; for (int row = -rows2; row <= rows2; row++) { int iy = y + row; int ioffset; if (0 <= iy && iy < height) ioffset = iy*width; else if (edgeAction == EdgeMode.Clamp) ioffset = y*width; else if (edgeAction == EdgeMode.Wrap) 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 == EdgeMode.Clamp) ix = x; else if (edgeAction == EdgeMode.Wrap) ix = (x + width)%width; else continue; } int rgb = inPixels[ioffset + ix]; a += f*((rgb >> 24) & 0xff); r += f*((rgb >> 16) & 0xff); g += f*((rgb >> 8) & 0xff); b += f*(rgb & 0xff); } } } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } }
/// <summary> /// Blur and transpose a block of ARGB pixels. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="premultiply"></param> /// <param name="unpremultiply"></param> /// <param name="edgeAction"></param> public static void ConvolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, bool premultiply, bool unpremultiply, EdgeMode edgeAction) { float[] matrix = kernel.GetKernel(); int cols = kernel.Width; 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 = 0, g = 0, b = 0, a = 0; 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 == EdgeMode.Clamp) ix = 0; else if (edgeAction == EdgeMode.Wrap) ix = (x + width)%width; } else if (ix >= width) { if (edgeAction == EdgeMode.Clamp) ix = width - 1; else if (edgeAction == EdgeMode.Wrap) ix = (x + width)%width; } int rgb = inPixels[ioffset + ix]; int pa = (rgb >> 24) & 0xff; int pr = (rgb >> 16) & 0xff; int pg = (rgb >> 8) & 0xff; int pb = rgb & 0xff; if (premultiply) { float a255 = pa*(1.0f/255.0f); pr = (int)(pr*a255); pg = (int)(pg*a255); pb = (int)(pb*a255); } a += f*pa; r += f*pr; g += f*pg; b += f*pb; } } if (unpremultiply && a != 0 && a != 255) { float f = 255.0f/a; r *= f; g *= f; b *= f; } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index] = (ia << 24) | (ir << 16) | (ig << 8) | ib; index += height; } } }
/// <summary> /// Convolve with a kernel consisting of one column. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="edgeAction"></param> public static void ConvolveV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction) { int index = 0; float[] matrix = kernel.GetKernel(); int rows = kernel.Height; int rows2 = rows / 2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; for (int row = -rows2; row <= rows2; row++) { int iy = y + row; int ioffset; if (iy < 0) { if (edgeAction == EdgeMode.Clamp) { ioffset = 0; } else if (edgeAction == EdgeMode.Wrap) { ioffset = ((y + height) % height) * width; } else { ioffset = iy * width; } } else if (iy >= height) { if (edgeAction == EdgeMode.Clamp) { ioffset = (height - 1) * width; } else if (edgeAction == EdgeMode.Wrap) { ioffset = ((y + height) % height) * width; } else { ioffset = iy * width; } } else { ioffset = iy * width; } float f = matrix[row + rows2]; if (f != 0) { int rgb = inPixels[ioffset + x]; a += f * ((rgb >> 24) & 0xff); r += f * ((rgb >> 16) & 0xff); g += f * ((rgb >> 8) & 0xff); b += f * (rgb & 0xff); } } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } }
/// <summary> /// Convolve with a 2D kernel. /// </summary> /// <param name="kernel"></param> /// <param name="inPixels"></param> /// <param name="outPixels"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="alpha"></param> /// <param name="edgeAction"></param> public static void ConvolveHV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction) { int index = 0; float[] matrix = kernel.GetKernel(); int rows = kernel.Height; int cols = kernel.Width; int rows2 = rows / 2; int cols2 = cols / 2; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float r = 0, g = 0, b = 0, a = 0; for (int row = -rows2; row <= rows2; row++) { int iy = y + row; int ioffset; if (0 <= iy && iy < height) { ioffset = iy * width; } else if (edgeAction == EdgeMode.Clamp) { ioffset = y * width; } else if (edgeAction == EdgeMode.Wrap) { 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 == EdgeMode.Clamp) { ix = x; } else if (edgeAction == EdgeMode.Wrap) { ix = (x + width) % width; } else { continue; } } int rgb = inPixels[ioffset + ix]; a += f * ((rgb >> 24) & 0xff); r += f * ((rgb >> 16) & 0xff); g += f * ((rgb >> 8) & 0xff); b += f * (rgb & 0xff); } } } int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff; int ir = PixelUtils.Clamp((int)(r + 0.5)); int ig = PixelUtils.Clamp((int)(g + 0.5)); int ib = PixelUtils.Clamp((int)(b + 0.5)); outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib; } } }