废话不多说,直接上代码:
public void SetPix(BitmapData bmd, int x, int y, Color newColor)
{
unsafe
{
int PixelSize = 4;
byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);
row[x * PixelSize] = newColor.B;
row[x * PixelSize + 1] = newColor.G;
row[x * PixelSize + 2] = newColor.R;
row[x * PixelSize + 3] = newColor.A;
}
}
public Color GetPix(BitmapData bmd, int x, int y)
{
unsafe
{
int PixelSize = 4;
byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);
int b = row[x * PixelSize];
int g=row[x * PixelSize + 1] ;
int r = row[x * PixelSize + 2];
int a = row[x * PixelSize + 3];
return Color.FromArgb(a, r, g, b);
}
}
public void floodFillScanLineWithStack(Bitmap map, int x, int y, Color newColor)
{
BitmapData bmd = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadOnly, map.PixelFormat);
Color oldColor = GetPix(bmd, x, y);
if (oldColor.R == newColor.R && oldColor.G == newColor.G && oldColor.B == newColor.B && oldColor.A == newColor.A)
{
map.UnlockBits(bmd);
return;
}
Stack<int> stackX = new Stack<int>();
Stack<int> stackY = new Stack<int>();
int y1;
bool spanLeft, spanRight;
stackX.Push(x);
stackY.Push(y);
while (stackX.Count > 0 && stackY.Count > 0)
{
x = stackX.Pop();
y = stackY.Pop();
y1 = y;
while (y1 >= 0 && GetPix(bmd, x, y1) == oldColor)
{
y1--;
}
y1++;
spanLeft = false;
spanRight = false;
while (y1 < map.Height - 1 && GetPix(bmd, x, y1) == oldColor)
{
SetPix(bmd, x, y1, newColor);
if (!spanLeft && x > 0 && GetPix(bmd, x - 1, y1) == oldColor)
{
stackX.Push(x - 1);
stackY.Push(y1);
spanLeft = true;
}
else if (spanLeft && x > 0 && GetPix(bmd, x - 1, y1) != oldColor)
{
spanLeft = false;
}
if (!spanRight && x < map.Width - 1 && GetPix(bmd, x + 1, y1) == oldColor)
{
stackX.Push(x + 1);
stackY.Push(y1);
spanRight = true;
}
else if (spanRight && x < map.Width - 1 && GetPix(bmd, x + 1, y1) != oldColor)
{
spanRight = false;
}
y1++;
}
}
map.UnlockBits(bmd);
}