Zuerst ein paar Anmerkungen zum Code, wo Dinge auftauchen, die ich für umständlich bzw. komisch gelöst halte:
1) In diesem Fall würde ich eine Nested-Function verwenden, um u.a. das mehrmalige Übergeben der Map zu umgehen. Das verhindert auch, dass die Map von aussen mitgegeben werden muss, was ja garkeinen Sinn ergibt, da sie rein interne Angelegenheit des Floodfills ist. Strukturell in etwa so:
Delphi-Quellcode:
procedure FloodFill(ABmp: TBitmap; x, y: Integer; AColor: TColor; Border: TColor);
var
Map: TBoolmap;
ix, iy: Integer;
procedure DoPixel(ax, ay: Integer);
begin
if ({ax und ay im gültigen Bereich}) and not Map[ax, ay] then
begin
ABmp.Canvas.Pixels[ax, ay] := Zielfarbe;
Map[ax, ay] := true;
DoPixel(ax+1, ay );
DoPixel(ax , ay+1);
DoPixel(ax-1, ay );
DoPixel(ax , ay-1);
end;
end;
begin
// Bei SetLength gehen so viele Argumente wie dein Array Dimensionen hat ;)
// Zudem ist es so "richtig herum", erst x dann y Koordinate. Bei dir ists vertauscht
// und damit anders herum als bei Pixels. Unschön und fehlerträchtig.
SetLength(Map, ABmp.Width, ABmp.Height);
// Map initialisieren, und dabei gleich die Border abtragen. Erspart die zusätzliche
// Abfrage auf diese für jedes Pixel nachher.
for iy := 0 to ABmp.Heigt-1 do
for ix := 0 to ABmp.Width-1 do
if ABmp.Canvas.Pixels[ix, iy] = Border then
Map[ix, iy] := true
else
Map[ix, iy] := false;
// Eigentichen Fill starten
DoPixel(x, y);
end;
So in etwa würd ich das vermutlich machen =)
2)(x <= ABmp.Width-1) and (y <= ABmp.Height-1)
Naja, ich hab zwar geschrieben, dass es bis Width/Height-1 geht, aber performanter und lesbarer wäre es gewesen statt obigem folgendes zu machen:
(x < ABmp.Width) and (y < ABmp.Height)
Selber Effekt, ohne noch zusätzliche Arithmetik. Und wenn ich nicht irre, ist ein Vergleich auf echt kleiner oder größer sogar noch ne Picosekunde schneller als auf kleiner/größer-gleich
3) Dein Stack overflow ist im übrigen interessant! Ich hätte eher eine Bereichsverletzung, oder mindestens ne
AV erwartet. Bei:
Greifst du auf Elemente zu, die evtl. garnicht mehr im Bereich sind. Ob x und y zwischen 0 und Width/Height sind, prüfst du erst später.
Gruss,
Fabian
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel