public static unsafe void FillStencilByColor(Surface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection) { int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRegionScansReadOnlyInt(); } } else { scans = new Rectangle[0]; } foreach (Rectangle rect in scans) { stencil.Set(rect, true); } for (int y = 0; y < surface.Height; ++y) { bool foundPixelInRow = false; ColorBgra *ptr = surface.GetRowAddressUnchecked(y); for (int x = 0; x < surface.Width; ++x) { if (CheckColor(cmp, *ptr, tolerance)) { stencil.SetUnchecked(x, y, true); if (x < left) { left = x; } if (x > right) { right = x; } foundPixelInRow = true; } ++ptr; } if (foundPixelInRow) { if (y < top) { top = y; } if (y >= bottom) { bottom = y; } } } foreach (Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1); }
public unsafe static void FillStencilByColor(ImageSurface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance, out Rectangle boundingBox, Gdk.Region limitRegion, bool limitToSelection) { int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Gdk.Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (Gdk.Region excluded = Gdk.Region.Rectangle(new Gdk.Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRectangles(); } } else { scans = new Gdk.Rectangle[0]; } foreach (Gdk.Rectangle rect in scans) { stencil.Set(rect, true); } Parallel.For(0, surface.Height, y => { bool foundPixelInRow = false; ColorBgra *ptr = surface.GetRowAddressUnchecked(y); int surfaceWidth = surface.Width; for (int x = 0; x < surfaceWidth; ++x) { if (CheckColor(cmp, *ptr, tolerance)) { stencil.SetUnchecked(x, y, true); if (x < left) { left = x; } if (x > right) { right = x; } foundPixelInRow = true; } ++ptr; } if (foundPixelInRow) { if (y < top) { top = y; } if (y >= bottom) { bottom = y; } } }); foreach (Gdk.Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = new Rectangle(left, top, right - left + 1, bottom - top + 1); }
public static unsafe void FillStencilFromPoint(Surface surface, IBitVector2D stencil, Point start, int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection) { ColorBgra cmp = surface[start]; int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRegionScansReadOnlyInt(); } } else { scans = new Rectangle[0]; } foreach (Rectangle rect in scans) { stencil.Set(rect, true); } Queue<Point> queue = new Queue<Point>(16); queue.Enqueue(start); while (queue.Count > 0) { Point pt = queue.Dequeue(); ColorBgra* rowPtr = surface.GetRowAddressUnchecked(pt.Y); int localLeft = pt.X - 1; int localRight = pt.X; while (localLeft >= 0 && !stencil.GetUnchecked(localLeft, pt.Y) && CheckColor(cmp, rowPtr[localLeft], tolerance)) { stencil.SetUnchecked(localLeft, pt.Y, true); --localLeft; } while (localRight < surface.Width && !stencil.GetUnchecked(localRight, pt.Y) && CheckColor(cmp, rowPtr[localRight], tolerance)) { stencil.SetUnchecked(localRight, pt.Y, true); ++localRight; } ++localLeft; --localRight; if (pt.Y > 0) { int sleft = localLeft; int sright = localLeft; ColorBgra* rowPtrUp = surface.GetRowAddressUnchecked(pt.Y - 1); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked(sx, pt.Y - 1) && CheckColor(cmp, rowPtrUp[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y - 1)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y - 1)); } } if (pt.Y < surface.Height - 1) { int sleft = localLeft; int sright = localLeft; ColorBgra* rowPtrDown = surface.GetRowAddressUnchecked(pt.Y + 1); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked(sx, pt.Y + 1) && CheckColor(cmp, rowPtrDown[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y + 1)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y + 1)); } } if (localLeft < left) { left = localLeft; } if (localRight > right) { right = localRight; } if (pt.Y < top) { top = pt.Y; } if (pt.Y > bottom) { bottom = pt.Y; } } foreach (Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1); }
public unsafe static void FillStencilFromPoint(ImageSurface surface, IBitVector2D stencil, Point start, int tolerance, out Rectangle boundingBox, Gdk.Region limitRegion, bool limitToSelection) { ColorBgra cmp = surface.GetColorBgra(start.X, start.Y); int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Gdk.Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (Gdk.Region excluded = Gdk.Region.Rectangle(new Gdk.Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRectangles(); } } else { scans = new Gdk.Rectangle[0]; } foreach (Gdk.Rectangle rect in scans) { stencil.Set(rect, true); } Queue <Point> queue = new Queue <Point> (16); queue.Enqueue(start); while (queue.Count > 0) { Point pt = queue.Dequeue(); ColorBgra *rowPtr = surface.GetRowAddressUnchecked(pt.Y); int localLeft = pt.X - 1; int localRight = pt.X; while (localLeft >= 0 && !stencil.GetUnchecked(localLeft, pt.Y) && CheckColor(cmp, rowPtr[localLeft], tolerance)) { stencil.SetUnchecked(localLeft, pt.Y, true); --localLeft; } int surfaceWidth = surface.Width; while (localRight < surfaceWidth && !stencil.GetUnchecked(localRight, pt.Y) && CheckColor(cmp, rowPtr[localRight], tolerance)) { stencil.SetUnchecked(localRight, pt.Y, true); ++localRight; } ++localLeft; --localRight; Action <int> checkRow = (row) => { int sleft = localLeft; int sright = localLeft; ColorBgra *otherRowPtr = surface.GetRowAddressUnchecked(row); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked(sx, row) && CheckColor(cmp, otherRowPtr[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, row)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, row)); } }; if (pt.Y > 0) { checkRow(pt.Y - 1); } if (pt.Y < surface.Height - 1) { checkRow(pt.Y + 1); } if (localLeft < left) { left = localLeft; } if (localRight > right) { right = localRight; } if (pt.Y < top) { top = pt.Y; } if (pt.Y > bottom) { bottom = pt.Y; } } foreach (Gdk.Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = new Rectangle(left, top, right - left + 1, bottom - top + 1); }
public unsafe static void FillStencilByColor (ImageSurface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance, out Rectangle boundingBox, Gdk.Region limitRegion, bool limitToSelection) { int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Gdk.Rectangle[] scans; stencil.Clear (false); if (limitToSelection) { using (Gdk.Region excluded = Gdk.Region.Rectangle (new Gdk.Rectangle (0, 0, stencil.Width, stencil.Height))) { excluded.Xor (limitRegion); scans = excluded.GetRectangles (); } } else { scans = new Gdk.Rectangle[0]; } foreach (Gdk.Rectangle rect in scans) stencil.Set (rect, true); Parallel.For(0, surface.Height, y => { bool foundPixelInRow = false; ColorBgra* ptr = surface.GetRowAddressUnchecked(y); int surfaceWidth = surface.Width; for (int x = 0; x < surfaceWidth; ++x) { if (CheckColor(cmp, *ptr, tolerance)) { stencil.SetUnchecked(x, y, true); if (x < left) { left = x; } if (x > right) { right = x; } foundPixelInRow = true; } ++ptr; } if (foundPixelInRow) { if (y < top) { top = y; } if (y >= bottom) { bottom = y; } } }); foreach (Gdk.Rectangle rect in scans) stencil.Set (rect, false); boundingBox = new Rectangle (left, top, right - left + 1, bottom - top + 1); }
public unsafe static void FillStencilFromPoint (ImageSurface surface, IBitVector2D stencil, Point start, int tolerance, out Rectangle boundingBox, Gdk.Region limitRegion, bool limitToSelection) { ColorBgra cmp = surface.GetColorBgraUnchecked (start.X, start.Y); int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Gdk.Rectangle[] scans; stencil.Clear (false); if (limitToSelection) { using (Gdk.Region excluded = Gdk.Region.Rectangle (new Gdk.Rectangle (0, 0, stencil.Width, stencil.Height))) { excluded.Xor (limitRegion); scans = excluded.GetRectangles (); } } else { scans = new Gdk.Rectangle[0]; } foreach (Gdk.Rectangle rect in scans) { stencil.Set (rect, true); } Queue<Point> queue = new Queue<Point> (16); queue.Enqueue (start); while (queue.Count > 0) { Point pt = queue.Dequeue (); ColorBgra* rowPtr = surface.GetRowAddressUnchecked (pt.Y); int localLeft = pt.X - 1; int localRight = pt.X; while (localLeft >= 0 && !stencil.GetUnchecked (localLeft, pt.Y) && CheckColor (cmp, rowPtr[localLeft], tolerance)) { stencil.SetUnchecked (localLeft, pt.Y, true); --localLeft; } int surfaceWidth = surface.Width; while (localRight < surfaceWidth && !stencil.GetUnchecked (localRight, pt.Y) && CheckColor (cmp, rowPtr[localRight], tolerance)) { stencil.SetUnchecked (localRight, pt.Y, true); ++localRight; } ++localLeft; --localRight; Action<int> checkRow = (row) => { int sleft = localLeft; int sright = localLeft; ColorBgra* otherRowPtr = surface.GetRowAddressUnchecked (row); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked (sx, row) && CheckColor (cmp, otherRowPtr[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue (new Point (sleft, row)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue (new Point (sleft, row)); } }; if (pt.Y > 0) { checkRow (pt.Y - 1); } if (pt.Y < surface.Height - 1) { checkRow (pt.Y + 1); } if (localLeft < left) { left = localLeft; } if (localRight > right) { right = localRight; } if (pt.Y < top) { top = pt.Y; } if (pt.Y > bottom) { bottom = pt.Y; } } foreach (Gdk.Rectangle rect in scans) stencil.Set (rect, false); boundingBox = new Rectangle (left, top, right - left + 1, bottom - top + 1); }
public unsafe static void FillStencilByColor(Surface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection) { int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRegionScansReadOnlyInt(); } } else { scans = new Rectangle[0]; } foreach (Rectangle rect in scans) { stencil.Set(rect, true); } for (int y = 0; y < surface.Height; ++y) { bool foundPixelInRow = false; ColorBgra *ptr = surface.GetRowAddressUnchecked(y); for (int x = 0; x < surface.Width; ++x) { if (CheckColor(cmp, *ptr, tolerance)) { stencil.SetUnchecked(x, y, true); if (x < left) { left = x; } if (x > right) { right = x; } foundPixelInRow = true; } ++ptr; } if (foundPixelInRow) { if (y < top) { top = y; } if (y >= bottom) { bottom = y; } } } foreach (Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1); }
public unsafe static void FillStencilFromPoint(Surface surface, IBitVector2D stencil, Point start, int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection) { ColorBgra cmp = surface[start]; int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRegionScansReadOnlyInt(); } } else { scans = new Rectangle[0]; } foreach (Rectangle rect in scans) { stencil.Set(rect, true); } Queue <Point> queue = new Queue <Point>(16); queue.Enqueue(start); while (queue.Count > 0) { Point pt = queue.Dequeue(); ColorBgra *rowPtr = surface.GetRowAddressUnchecked(pt.Y); int localLeft = pt.X - 1; int localRight = pt.X; while (localLeft >= 0 && !stencil.GetUnchecked(localLeft, pt.Y) && CheckColor(cmp, rowPtr[localLeft], tolerance)) { stencil.SetUnchecked(localLeft, pt.Y, true); --localLeft; } while (localRight < surface.Width && !stencil.GetUnchecked(localRight, pt.Y) && CheckColor(cmp, rowPtr[localRight], tolerance)) { stencil.SetUnchecked(localRight, pt.Y, true); ++localRight; } ++localLeft; --localRight; if (pt.Y > 0) { int sleft = localLeft; int sright = localLeft; ColorBgra *rowPtrUp = surface.GetRowAddressUnchecked(pt.Y - 1); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked(sx, pt.Y - 1) && CheckColor(cmp, rowPtrUp[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y - 1)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y - 1)); } } if (pt.Y < surface.Height - 1) { int sleft = localLeft; int sright = localLeft; ColorBgra *rowPtrDown = surface.GetRowAddressUnchecked(pt.Y + 1); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked(sx, pt.Y + 1) && CheckColor(cmp, rowPtrDown[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y + 1)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y + 1)); } } if (localLeft < left) { left = localLeft; } if (localRight > right) { right = localRight; } if (pt.Y < top) { top = pt.Y; } if (pt.Y > bottom) { bottom = pt.Y; } } foreach (Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1); }