static void PrepareVerticalMinMax(int width, int height, int radius, LimitMinMax[] limitMinMax) { int heightMinus1 = height - 1; for (int y = height - 1; y >= 0; --y) { limitMinMax[y] = new LimitMinMax( min(y + radius + 1, heightMinus1) * width, max(y - radius, 0) * width); } }
//------------------------------------------------ static void PrepareHorizontalMinMax(int width, int radius, LimitMinMax[] limitMinMax) { int widthMinus1 = width - 1; for (int x = width - 1; x >= 0; --x) { limitMinMax[x] = new LimitMinMax( min(x + radius + 1, widthMinus1), max(x - radius, 0)); } }
public static void FastBlur32ARGB(int[] srcBuffer, int[] dest, int srcImageWidth, int srcImageHeight, int radius) { if (srcImageWidth < 1) { return; } //--------------------------------------------- //assign dimension info and copy buffer int width = srcImageWidth; int height = srcImageHeight; int wh = width * height; var r_buffer = new byte[wh]; var g_buffer = new byte[wh]; var b_buffer = new byte[wh]; var a_buffer = new byte[wh]; int p1, p2; LimitMinMax[] limitMinMax = new LimitMinMax[max(width, height)]; //------------------------------ //look up table : depends on radius, var dvLookup = PrepareLookupTable(radius); //------------------------------ PrepareHorizontalMinMax(width, radius, limitMinMax); int px_row_head = 0; int pixel_index = 0; for (int y = 0; y < height; y++) { // blur horizontal int rsum, gsum, bsum, asum; CalculateSumARGBHorizontal(srcBuffer, width, pixel_index, radius, out rsum, out gsum, out bsum, out asum); for (int x = 0; x < width; x++) { r_buffer[pixel_index] = dvLookup[rsum]; g_buffer[pixel_index] = dvLookup[gsum]; b_buffer[pixel_index] = dvLookup[bsum]; a_buffer[pixel_index] = dvLookup[asum]; LimitMinMax lim = limitMinMax[x]; p1 = srcBuffer[px_row_head + lim.Min]; p2 = srcBuffer[px_row_head + lim.Max]; rsum += ((p1 >> R_SHIFT) & 0xff) - ((p2 >> R_SHIFT) & 0xff); gsum += ((p1 >> G_SHIFT) & 0xff) - ((p2 >> G_SHIFT) & 0xff); bsum += ((p1 >> B_SHIFT) & 0xff) - ((p2 >> B_SHIFT) & 0xff); asum += ((p1 >> A_SHIFT) & 0xff) - ((p2 >> A_SHIFT) & 0xff); pixel_index++; } //go next row px_row_head += width; } PrepareVerticalMinMax(width, height, radius, limitMinMax); //------------------------------------------------------------------- for (int x = 0; x < width; x++) { // blur vertical int rsum, gsum, bsum, asum; rsum = gsum = bsum = asum = 0; //----------------------------- int yp = -radius * width; for (int i = -radius; i <= 0; ++i) { pixel_index = x; rsum += r_buffer[pixel_index]; gsum += g_buffer[pixel_index]; bsum += b_buffer[pixel_index]; asum += a_buffer[pixel_index]; yp += width; } for (int i = 1; i <= radius; ++i) { pixel_index = yp + x; rsum += r_buffer[pixel_index]; gsum += g_buffer[pixel_index]; bsum += b_buffer[pixel_index]; asum += a_buffer[pixel_index]; yp += width; } //----------------------------- pixel_index = x; for (int y = 0; y < height; y++) { //assign pixel value here dest[pixel_index] = (int)((uint)(dvLookup[rsum] << R_SHIFT) | (uint)(dvLookup[gsum] << G_SHIFT) | (uint)(dvLookup[bsum] << B_SHIFT) | unchecked ((uint)(dvLookup[asum] << A_SHIFT))); var limit = limitMinMax[y]; p1 = x + limit.Min; p2 = x + limit.Max; rsum += r_buffer[p1] - r_buffer[p2]; //diff between 2 pixels gsum += g_buffer[p1] - g_buffer[p2]; //diff between 2 pixels bsum += b_buffer[p1] - b_buffer[p2]; //diff between 2 pixels asum += a_buffer[p1] - a_buffer[p2]; pixel_index += width; } } }
public static void FastBlur32ARGB(int[] srcBuffer, int[] dest, int srcImageWidth, int srcImageHeight, int radius) { if (srcImageWidth < 1) { return; } //--------------------------------------------- //assign dimension info and copy buffer int width = srcImageWidth; int height = srcImageHeight; int wh = width * height; var r_buffer = new byte[wh]; var g_buffer = new byte[wh]; var b_buffer = new byte[wh]; var a_buffer = new byte[wh]; int p1, p2; LimitMinMax[] limitMinMax = new LimitMinMax[max(width, height)]; //------------------------------ //look up table : depends on radius, var dvLookup = PrepareLookupTable(radius); //------------------------------ PrepareHorizontalMinMax(width, radius, limitMinMax); int px_row_head = 0; int pixel_index = 0; for (int y = 0; y < height; y++) { // blur horizontal int rsum, gsum, bsum, asum; CalculateSumARGBHorizontal(srcBuffer, width, pixel_index, radius, out rsum, out gsum, out bsum, out asum); for (int x = 0; x < width; x++) { r_buffer[pixel_index] = dvLookup[rsum]; g_buffer[pixel_index] = dvLookup[gsum]; b_buffer[pixel_index] = dvLookup[bsum]; a_buffer[pixel_index] = dvLookup[asum]; LimitMinMax lim = limitMinMax[x]; p1 = srcBuffer[px_row_head + lim.Min]; p2 = srcBuffer[px_row_head + lim.Max]; rsum += ((p1 >> R_SHIFT) & 0xff) - ((p2 >> R_SHIFT) & 0xff); gsum += ((p1 >> G_SHIFT) & 0xff) - ((p2 >> G_SHIFT) & 0xff); bsum += ((p1 >> B_SHIFT) & 0xff) - ((p2 >> B_SHIFT) & 0xff); asum += ((p1 >> A_SHIFT) & 0xff) - ((p2 >> A_SHIFT) & 0xff); pixel_index++; } //go next row px_row_head += width; } PrepareVerticalMinMax(width, height, radius, limitMinMax); //------------------------------------------------------------------- for (int x = 0; x < width; x++) { // blur vertical int rsum, gsum, bsum, asum; rsum = gsum = bsum = asum = 0; //----------------------------- int yp = -radius * width; for (int i = -radius; i <= 0; ++i) { pixel_index = x; rsum += r_buffer[pixel_index]; gsum += g_buffer[pixel_index]; bsum += b_buffer[pixel_index]; asum += a_buffer[pixel_index]; yp += width; } for (int i = 1; i <= radius; ++i) { pixel_index = yp + x; rsum += r_buffer[pixel_index]; gsum += g_buffer[pixel_index]; bsum += b_buffer[pixel_index]; asum += a_buffer[pixel_index]; yp += width; } //----------------------------- pixel_index = x; for (int y = 0; y < height; y++) { //assign pixel value here dest[pixel_index] = (int)((uint)(dvLookup[rsum] << R_SHIFT) | (uint)(dvLookup[gsum] << G_SHIFT) | (uint)(dvLookup[bsum] << B_SHIFT) | unchecked((uint)(dvLookup[asum] << A_SHIFT))); var limit = limitMinMax[y]; p1 = x + limit.Min; p2 = x + limit.Max; rsum += r_buffer[p1] - r_buffer[p2]; //diff between 2 pixels gsum += g_buffer[p1] - g_buffer[p2]; //diff between 2 pixels bsum += b_buffer[p1] - b_buffer[p2]; //diff between 2 pixels asum += a_buffer[p1] - a_buffer[p2]; pixel_index += width; } } }