I am making a GIF editor in C#, and I am currently working on the eraser tool. I am not sure what I can do to make it more efficient, because when I make the thickness (diameter) more than 30 (pixels) it starts to get a bit slow.
if (click && eraserSelected) { new Thread(() => { Application.Current.Dispatcher.Invoke((Action)(() => b = imageBox.Source as WriteableBitmap)); Application.Current.Dispatcher.Invoke((Action)(() => endPoint = Mouse.GetPosition(imageBox))); System.Windows.Media.Color color; System.Windows.Point[] linePixels = FindPixels.Line(startPoint, endPoint).ToArray(); int[][][] pixels = new int[linePixels.Length][][]; for (int i = 0; i < linePixels.Length; i++) pixels[i] = FindPixels.Circle(thickness, (int)linePixels[i].X, (int)linePixels[i].Y); Bitmap originalFrame = gifFrames.GetOriginalFrame(); Application.Current.Dispatcher.Invoke((() => { for (int j = 0; j < pixels.Length; j++) for (int i = 0; i < pixels[j][0].Length; i++) if (pixels[j][0][i] < pixelsEdited[0].Count() && pixels[j][0][i] >= 0 && pixels[j][1][i] < pixelsEdited.Count() && pixels[j][1][i] >= 0) if (!pixelsEdited[pixels[j][1][i]][pixels[j][0][i]]) { color = System.Windows.Media.Color.FromRgb(originalFrame.GetPixel(pixels[j][0][i], pixels[j][1][i]).R, originalFrame.GetPixel(pixels[j][0][i], pixels[j][1][i]).G, originalFrame.GetPixel(pixels[j][0][i], pixels[j][1][i]).B); try { b.SetPixel(pixels[j][0][i], pixels[j][1][i], color); pixelsEdited[pixels[j][1][i]][pixels[j][0][i]] = true; } catch { } } })); Application.Current.Dispatcher.Invoke((Action)(() => startPoint = endPoint)); }).Start(); } That is the code for the eraser tool itself. Here is the code for the FindPixels.Line() and FindPixels.Circle() functions:
class FindPixels { /// <summary> /// Finds all the pixels that are within a circle of a given diameter, and center /// </summary> /// <param name="diameter"></param> /// <param name="centerX"></param> /// <param name="centerY"></param> /// <returns>All the pixels within a circle</returns> public static int[][] Circle(int diameter, int centerX, int centerY) { int radius = diameter / 2; List<int> pixelsX = new List<int>(); List<int> pixelsY = new List<int>(); for (int x = centerX - radius; x < centerX + radius; x++) { for (int y = centerY - radius; y < centerY + radius; y++) { double dx = x - centerX; double dy = y - centerY; double distanceSquared = dx * dx + dy * dy; if (distanceSquared <= radius * radius) { int distance = y - (centerY - radius); for (int i = 0; i < diameter - distance * 2; i++) { pixelsX.Add(x); pixelsY.Add(y + i); } break; } } } int[][] pixels = { pixelsX.ToArray(), pixelsY.ToArray() }; return pixels; } /// <summary> /// Finds all pixels that form a line /// </summary> /// <param name="startPoint"></param> /// <param name="endPoint"></param> /// <returns>All points within the two points given</returns> public static List<Point> Line(Point p0, Point p1) { int x0 = (int)p0.X; int y0 = (int)p0.Y; int x1 = (int)p1.X; int y1 = (int)p1.Y; int dx = Math.Abs(x1 - x0); int dy = Math.Abs(y1 - y0); int sx = x0 < x1 ? 1 : -1; int sy = y0 < y1 ? 1 : -1; int err = dx - dy; var points = new List<Point>(); while (true) { points.Add(new Point(x0, y0)); if (x0 == x1 && y0 == y1) break; int e2 = 2 * err; if (e2 > -dy) { err = err - dy; x0 = x0 + sx; } if (e2 < dx) { err = err + dx; y0 = y0 + sy; } } return points; } } What I was thinking was instead of drawing a bunch of circles on each pixel of the line, I draw the start and end point and then do a rectangle to connect them, but how would I find the points connecting them.
Here is a picture of what I mean:
The red points are what I am having trouble finding, and all the points withing the pink outline are what I would change.
