public static bool ExpandRectangle(SpriteIsland r, int x, int y) { if (x >= r.X && y >= r.Y && x < r.X + r.Width && y < r.Y + r.Height) { return true; } bool expanded = false; if (x >= r.X && x <= r.X + r.Width) { if (y == r.Y - 1) { r.Y--; r.Height++; expanded = true; } if (y == r.Y + r.Height) { r.Height++; expanded = true; } } if (y >= r.Y && y <= r.Y + r.Height) { if (x == r.X - 1) { r.X--; r.Width++; expanded = true; } if (x == r.X + r.Width) { r.Width++; expanded = true; } } return expanded; }
public static SpriteIsland Clip(SpriteIsland a, SpriteIsland b) { int nx = Math.Max(a.X, b.X); int ny = Math.Max(a.Y, b.Y); int nw = Math.Min(a.X + a.Width, b.X + b.Width) - nx; int nh = Math.Min(a.Y + a.Height, b.Y + b.Height) - ny; return new SpriteIsland(nx, ny, nw, nh); }
public void TestExpandRectangle6() { var r = new SpriteIsland(0, 0, 10, 10); Assert.True(!SpriteAnalyzer.ExpandRectangle(r, -2, -2)); Assert.True(r.X == 0); Assert.True(r.Y == 0); Assert.True(r.Width == 10); Assert.True(r.Height == 10); }
/// <summary> /// Erase an island from image. /// </summary> /// <param name='buf'> /// The image to erase the island from. /// </param> /// <param name='rect'> /// An island to erase all pixels. /// </param> public static byte Erase(Pixbuf buf, SpriteIsland rect) { // Make sure not to read and write outside the image. var clip = SpriteIsland.Clip(rect, new SpriteIsland(0, 0, buf.Width, buf.Height)); byte max = 0; unsafe { byte* start = (byte*)buf.Pixels; int stride = buf.Rowstride; int startX = clip.X; int startY = clip.Y; int endX = clip.X + clip.Width; int endY = clip.Y + clip.Height; for (int y = startY; y < endY; y++) { for (int x = startX; x < endX; x++) { byte* current = start + 4 * x + y * stride; current[0] = current[1] = current[2] = current[3] = 0; } } } return max; }
public static List<SpriteIsland> FindIslands(Pixbuf buf) { var list = new List<SpriteIsland>(); // Grow rectangles when a pixel is touching the edge. // As one pixel might touch two rectangles, the rectangles will overlap. unsafe { byte* start = (byte*)buf.Pixels; int stride = buf.Rowstride; int w = buf.Width; int h = buf.Height; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { byte* current = start + x * 4 + y * stride; bool transparent = current[3] == 0; if (transparent) continue; // Search through list of rectangles. int listCount = list.Count; bool found = false; for (int i = 0; i < listCount; i++) { if (ExpandRectangle(list[i], x, y)) found = true; } // end searching through list of rectangles. if (found) continue; // Create a new rectangle containing only that pixel. var newRectangle = new SpriteIsland(x, y, 1, 1); list.Add(newRectangle); } } } // end unsafe block. // Join the overlapping rectangles. SpriteIsland.JoinOverlaps(list); return list; }
public static void Join(List<SpriteIsland> islands, int i, int j) { if (i == j) return; var r = islands[i]; var s = islands[j]; int nx, ny, nw, nh; nx = Math.Min(r.X, s.X); ny = Math.Min(r.Y, s.Y); nw = Math.Max(r.X + r.Width, s.X + s.Width) - nx; nh = Math.Max(r.Y + r.Height, s.Y + s.Height) - ny; islands[i] = new SpriteIsland(nx, ny, nw, nh); islands.RemoveAt(j); }
public static bool Intersects(SpriteIsland r, SpriteIsland s) { return r.X <= s.X + s.Width && r.Y <= s.Y + s.Height && r.X + r.Width >= s.X && r.Y + r.Height >= s.Y; }