public static void fill(Btm bm, int x, int y, Color oc, Color nc)
{
if (oc == nc) return;
Stack<Point> pt = new Stack<Point>();
pt.Push(new Point(x, y)); //затравка
var tmp = Point.Empty;
var xl = 0; //крайнее левое значение
var xr = 0; //правое
bm.LockBits();
while (pt.Count > 0)
{
tmp = pt.Pop();
y = tmp.Y;
x = tmp.X;
if (ColorMatchh(bm.GetPixel(x, y),oc)) {
bm.SetPixel(x, y, nc);
}
if(x>0)
x--;
while(ColorMatchh(bm.GetPixel(x,y),oc)) {
bm.SetPixel(x, y, nc);if(x>0)x--;
}
xl = x;
x = tmp.X + 1;
while (ColorMatchh(bm.GetPixel(x, y),oc)) {
bm.SetPixel(x, y, nc);if (x<bm.image.Width-1)x++;
}
xr = x;
for (int i = xl; i < xr; i++)
{
if (y<bm.image.Height-1 )
{
if (ColorMatchh(bm.GetPixel(i, y + 1),oc))
{
pt.Push(new Point(i, y + 1));
break;
}
}
}
for (int i = xl; i < xr; i++)
{
if (y > 0)
{
if (ColorMatchh(bm.GetPixel(i, y - 1),oc))
{
pt.Push(new Point(i, y - 1));
break;
}
}
}
}
bm.UnlockBits();
}
Это стековая реализация. Btm - мой вариант Bitmap, имеющий ссылку на объект Bitmap. Get/SetPixel реализованы при помощи Marshal.Copy().
LockBits - копирует данные, адресуемые BitmapData.Scan0 в byte массив, содержащий информацию о цветах пикселей . UnlockBits - наоборот. Также методы вызывают lock/unlockbits объекта Bitmap.
ColorMatchh - для сравнения цветов. Возвращает true, если они равны. Я думал, что реализовал ее быстрее стандартной перегруженной операции сравнения для Color - ан-нет, порой и медленнее выходит.
Сам алгоритм верен лишь отчасти. При желании, поймете, в чем ошибка. Прежде чем я ее исправлю, мне хотелось бы, чтобы вы мне помогли
- можно ли вообще избавиться от проверки на выход X,Y за пределы самого изображения, просто реализовав все так, чтобы в этом не было необходимости? Без проверок получается солидный выйгрыш в скорости.
- можно ли, не определяя цвет пикселя, понять, что он закрашен(допустим, создать массив bool, при заливке устанавливать соотв. пикселю флаг, перед заливкой сначала проверять этот флаг)?
- как можно быстрее сравнить цвета, разными там побитовыми операциями, и имеет ли смысл вообще пытаться реализовать это?
- можно ли контролировать ход закраски? Например - проверяется строка ниже. Закрашивается. Строка выше от нее точно закрашена(если ее диапазон крайних значений X больше, чем у текущей), поэтому ее можно не проверять
- какие есть слабые места у моей реализации(кроме той ошибки в ней, что я указал)?