BASICのグラフィックコマンドを作っていて、GDIには塗り潰しの機能が無い
(図形の塗り潰し描画はありますよ)
ふむ、やっと自分でグラフィック関係の処理が実装できる!
楽しい…
って事で、ペイント処理を作ってみました
おそらくロジック的には最速だと思います
(サーフェイスをロックして直接メモリを操作したり、コーディングでは高速化できます)
public void paint(Bitmap g,Point p,Color col)
{
const int BUFFER_SIZE = 1000;
Point[] stack = new Point[BUFFER_SIZE];
int x, y;
int wptr = 0, rptr = 0;
bool pf1, pf2, pf1buf, pf2buf;
if (p.X < 0 || p.X >= ScreenSize.Width || p.Y < 0 || p.Y >= ScreenSize.Height)
{
return;
}
Color bc = g.GetPixel(p.X, p.Y);
if (bc == col) return;
stack[wptr].X = p.X;
stack[wptr++].Y = p.Y;
while (wptr != rptr)
{
x = stack[rptr].X;
y = stack[rptr].Y;
pf1 = pf2 = true;
pf1buf = (y > 0 && g.GetPixel(x, y - 1) != bc);
pf2buf = (y < ScreenSize.Height - 1 && g.GetPixel(x, y + 1) != bc);
while (x >= 0 && g.GetPixel(x, y) == bc)
{
if (y > 0 && g.GetPixel(x, y - 1) == bc)
{
if (pf1)
{
stack[wptr].X = x;
stack[wptr++].Y = y - 1;
wptr %= BUFFER_SIZE;
pf1 = false;
}
}
else
{
pf1 = true;
}
if (y < ScreenSize.Height - 1 && g.GetPixel(x, y + 1) == bc)
{
if (pf2)
{
stack[wptr].X = x;
stack[wptr++].Y = y + 1;
wptr %= BUFFER_SIZE;
pf2 = false;
}
}
else
{
pf2 = true;
}
g.SetPixel(x--, y, col);
}
x = stack[rptr++].X+1;
rptr %= BUFFER_SIZE;
pf1 = pf1buf;
pf2 = pf2buf;
while (x < ScreenSize.Width && g.GetPixel(x, y) == bc)
{
if (y > 0 && g.GetPixel(x, y - 1) == bc)
{
if (pf1)
{
stack[wptr].X = x;
stack[wptr++].Y = y - 1;
wptr %= BUFFER_SIZE;
pf1 = false;
}
}
else
{
pf1 = true;
}
if (y < ScreenSize.Height - 1 && g.GetPixel(x, y + 1) == bc)
{
if (pf2)
{
stack[wptr].X = x;
stack[wptr++].Y = y + 1;
wptr %= BUFFER_SIZE;
pf2 = false;
}
}
else
{
pf2 = true;
}
g.SetPixel(x++, y, col);
}
}
}
指定された点から左右に塗り潰していき、この時に上下のポイントが塗り潰し不可から塗り潰し可になったらバッファに溜めて、処理を繰り返します
バッファはループバッファになっているので、バッファオーバーしたら塗り残しができます
コメント