Wypelnianie obszaru CANVAS

0

Witam,
jestem chory i dość słabo myślę, a chciałbym napisać w miare szybko taką funkcję. Chodzi mi o wypełnianie danego obszaru kolorem, odpowiednik FloodFill w Canvas (zaczynając od jednego piksela bada wszystkie sąsiadujące i te o danych parametrach zostają przebarwione). Mam tu niestety pewien problem. Wyskakują mi co chwila Stack Overflow'y. Pytanie moje brzmi jak moją procedure zmodyfikować najlepiej do repeat until itd.

procedure .. .Click(X, Y: Integer; C: TColor);
begin
if PtInRect(Point(X, Y), Image.ClientRect) then
if Image.Canvas.Pixels[x, Y] = clRed then
begin
Image.Canvas.Pixels[x, y] := C;
Click(X-1, Y, C);
Click(X+1, Y, C);
Click(X, Y-1, C);
Click(X, Y+1, C);

end;
end;

Kod może mieć błędy, napisałem go z pamięci, by pokazać idee. Procedura wysypuje się oczywiście przy większych połaciach - odwołuje się zbyt wiele razy sama do siebie i dochodzi do przepełnienia. Próbowałem szukać jakichś algorytmów nic niestety nie znalazłem, proszę o pomoc gdyż zależy mi na czasie anie bardzo myślę.

Zastanawiałem się w sumie by wykorzystać mechanizm, z którego korzystałem przy pisaniu języka skryptowego - nałożyć zakładek (label) i się odwoływać do nich zapisując każde odwołanie - na pewno prędkość działania bardzo spadnie ale algorytm będzie niezawodny. Macie może jednak bardziej "cywilizowane" pomysly?
Pozdrawiam, Patryk K.

0

Na pierwszy rzut oka ta procedura nie ma "punktu stopu", dlatego wywołania rekurencyjne idę w nieskończoność aż się stos przepełnia. Po prostu zamieniasz jeden kolor na inny i dalej ją wywołujesz BEZ PRZERWY. Idea jest taka, żeby ograniczyć obszar jakimś jednakowym kolorem i sprawdzać na początku procedury czy punkt jest brzegowy (o tym kolorze) i wtedy natychmiast kończyć procedurę (punkt stopu).

0

A nie, przepraszam, wygląda że jest dobrze. Może po prostu zwiększ stos (dla procedur rekurencyjnych) dyrektywą kompilatora {$MAXSTACKSIZE number}

0

Dziekuje za zainteresowanie tematem. Procedura oczywiście ma punkt stopu jeżeli C <> clRed - sama się zakończy. Zwiększę zaraz stos, mam nadzieję, że to mi pomoże (
niestety tylko w ograniczonym stopniu - próbując zamalowywać zdjęcia wielkości bilboardów oczywiście się i tak wysypie ;) ).
Co do informacji nt FloodFill na angielskiej wikipedii dokładnie ją przestudiuję, aczkolwiek wydaje mi się, że jest to oparte o rekurencję, której szczerze mówiąc chciałbym unikać.
Pozdrawiam, potestuje i zdam relacje ;))
Patryk

0
Patryk napisał(a)

wydaje mi się, że jest to oparte o rekurencję, której szczerze mówiąc chciałbym unikać.

a czego niby używasz w kodzie, który podałeś???

0

Punkt stopu jest, tyle że nie ma ograniczenia obszaru jednokolorowym pierścieniem i nie ma kontroli tego. Procedura sprawdza więc całą bitmapę i zamienia jeden kolor na inny. Czy tego chcesz? Jeśli tak, to nie trzeba rekurencji, wystarczy przelecieć wszystkie piksele podwójną pętlą iteracyjną.

0

Scanline nigdy osobiście nie próbowałem. Optymalizacja prędkości przydaje się wtedy, gdy faktycznie aplikacja działa za wolno (takie są zalecenia, żeby nie tracić czasu na przeróbki kodu na bardziej skomplikowany i mniej czytelny). Więc jeśli tych zamian koloru trzeba robić bardzo dużo (na przykład tysiące zdjęć z bazy danych), to wtedy scanline powinno bardzo przyspieszyć.

0

Tu jest niezły artykulik o scanline:
http://www.efg2.com/Lab/ImageProcessing/Scanline.htm

1 użytkowników online, w tym zalogowanych: 0, gości: 1