FloodFill () Funktioniert unter Linux nur bedingt

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.
Antworten
Jole
Beiträge: 116
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von Jole »

FloodFill Funktioniert unter Linux nur mit Rectangle/Polygpon oder Ellipse, wenn ich ein Polygon mit LineTo Zeichne nicht!? Außerdem muss ich zwei mal auf den Button drücken damit was passiert, gefüllt wird aber nichts.
Einfaches Beispiel

Code: Alles auswählen

 
procedure TForm1.Button1Click(Sender: TObject);
var x, y: Integer;
begin
  x:= PaintBox1.Canvas.Width div 2+ 1;
  y:= PaintBox1.Canvas.Height div 2+ 1;
 
  PaintBox1.Canvas.Brush.Style:= bsSolid;
  PaintBox1.Canvas.Brush.Color:= clGreen;
  PaintBox1.Canvas.Pen.Color:= clBlack;
 
  PaintBox1.Canvas.MoveTo(x, y- 50);
  PaintBox1.Canvas.LineTo(x+ 100, y+ 50);
  PaintBox1.Canvas.LineTo(x- 100, y+ 50);
  PaintBox1.Canvas.LineTo(x, y- 50);
 
  PaintBox1.Canvas.FloodFill(x, y, clBlack, fsBorder);
end;
 


BS: Linux Mint 18 cinnamon (64) / Lazarus 1.6/FPC 3.0.0.
Unter Windows Funktioniert das so wie erwartet.

Spin ich jetzt, oder ist das ein Bug?

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2256
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.8, FPC 3.0.4)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von m.fuchs »

Zeichenoperationen einer PaintBox immer nur im OnPaint durchführen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

wp_xyz
Beiträge: 3253
Registriert: Fr 8. Apr 2011, 09:01

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von wp_xyz »

Außerdem würde ich nicht Paintbox1.Canvas.Width nehmen, sondern Paintbox1.Width (genauso mit Height) - ich wusste gar nicht, dass der Canvas eine Breite und eine Höhe hat.

Zu deinem Problem: Ich habe dein Programm unter Linux gestartet und mit dem Debugger verfolgt. Es scheint tatsächlich so zu sein, dass unter Linux (getestet: gtk2, qt) kein FloodFill implementiert ist. Falls du nicht auf widgetset-unabhängige Graphik (bgrabitmap, opbitmap) ausweichen willst, könntest du diese Implementierung aus diesem Forum ausprobieren: viewtopic.php?f=25&t=3891

Jole
Beiträge: 116
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von Jole »

m.fuchs hat geschrieben:Zeichenoperationen einer PaintBox immer nur im OnPaint durchführen.

Da funktioniert es auch nicht. Ich hab gedacht das OnPaint bräuchte man gar nicht mehr für die PaintBox? Unter Windows funktioniert das ohne und wenn ich unter Linux Rectangle statt LineTo verwende auch. Also irgendwie seltsam.
wp_xyz hat geschrieben:Außerdem würde ich nicht Paintbox1.Canvas.Width nehmen, sondern Paintbox1.Width (genauso mit Height) - ich wusste gar nicht, dass der Canvas eine Breite und eine Höhe hat.

Und ich wusste nicht das es ohne Canvas geht, da kann man mal sehen :)
Wirklich brauchen tu ich das nicht, ich bin nur zufällig durch ne frage (die nichts mit FloodFill zu tun hat) in einem anderen Forum drauf gestoßen. Ich wollte nur mal wissen ob das schon jemandem aufgefallen ist.
FloodFill muss aber vorhanden sein, sonst würde es bei Rectangle oder Polygon ja auch nicht funktionieren.

wp_xyz
Beiträge: 3253
Registriert: Fr 8. Apr 2011, 09:01

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von wp_xyz »

Jole hat geschrieben:FloodFill muss aber vorhanden sein, sonst würde es bei Rectangle oder Polygon ja auch nicht funktionieren.

Nein, FloodFill und Füllen eines Rechtecks/Polygons haben nur gemeinsam, dass horizontale Linien in der Füllfarbe gezeichnet werden, aber wie die Endpunkte bestimmt werden, ist grundverschieden. Beim Rechteck sind das der bekannte linke/rechte Rand, beim Polygon wird der Schnittpunkt mit dem betreffenden Polygon-Segment berechnet, beim Floodfill sucht man, je nach Verfahren, wann ein Pixel entlang der horizontalen Linie die gewünschte Randfarbe hat bzw. wann die aktuelle Hintergrundfarbe sich ändert.

theo
Beiträge: 8318
Registriert: Mo 11. Sep 2006, 19:01

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von theo »

Jole hat geschrieben:Da funktioniert es auch nicht. Ich hab gedacht das OnPaint bräuchte man gar nicht mehr für die PaintBox? Unter Windows funktioniert das ohne und wenn ich unter Linux Rectangle statt LineTo verwende auch. Also irgendwie seltsam.


Es kann schon sein, dass es irgendwo "zufällig" funktioniert, aber es ist falsch und funktioniert dann halt auf anderen Plattformen nicht.
PaintBox hat keinen Buffer.
Also immer schön in OnPaint malen.

Jole
Beiträge: 116
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von Jole »

wp_xyz hat geschrieben:Nein, FloodFill und Füllen eines Rechtecks/Polygons haben nur gemeinsam, dass horizontale Linien in der Füllfarbe gezeichnet werden, aber wie die Endpunkte bestimmt werden, ist grundverschieden. Beim Rechteck sind das der bekannte linke/rechte Rand, beim Polygon wird der Schnittpunkt mit dem betreffenden Polygon-Segment berechnet, beim Floodfill sucht man, je nach Verfahren, wann ein Pixel entlang der horizontalen Linie die gewünschte Randfarbe hat bzw. wann die aktuelle Hintergrundfarbe sich ändert.

Irgendwie fällt es mir schwer das zu schlucken, denn woher will FloodFill denn wissen womit ein Rechteck gezeichnet wurde?
Das

Code: Alles auswählen

 
  PaintBox1.Canvas.MoveTo(0, 0);
  PaintBox1.Canvas.LineTo(99, 0);
  PaintBox1.Canvas.LineTo(99, 99);
  PaintBox1.Canvas.LineTo(0, 99);
  PaintBox1.Canvas.LineTo(0, 0);
 

ist doch das gleiche wie das

Code: Alles auswählen

 
  PaintBox1.Canvas.Rectangle(0, 0, 99, 99);
 

oder nicht?
Ich sollte noch erwähnen das ich mit Grafikmethoden unter Lazarus nur wenig vertraut bin, nutze sie so gut wie nie.
Aber wie auch immer, FloodFill scheint mit der Linux Version nur zur Hälfte zu funktionieren.
theo hat geschrieben:
Jole hat geschrieben:Da funktioniert es auch nicht. Ich hab gedacht das OnPaint bräuchte man gar nicht mehr für die PaintBox? Unter Windows funktioniert das ohne und wenn ich unter Linux Rectangle statt LineTo verwende auch. Also irgendwie seltsam.


Es kann schon sein, dass es irgendwo "zufällig" funktioniert, aber es ist falsch und funktioniert dann halt auf anderen Plattformen nicht.
PaintBox hat keinen Buffer.
Also immer schön in OnPaint malen.

Da hab ich mich wahrscheinlich dadurch täuschen lassen das alles neu gezeichnet wurde nach dem das Fenster verborgen war.

wp_xyz
Beiträge: 3253
Registriert: Fr 8. Apr 2011, 09:01

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von wp_xyz »

Jole hat geschrieben:
wp_xyz hat geschrieben:Nein, FloodFill und Füllen eines Rechtecks/Polygons haben nur gemeinsam, dass horizontale Linien in der Füllfarbe gezeichnet werden, aber wie die Endpunkte bestimmt werden, ist grundverschieden. Beim Rechteck sind das der bekannte linke/rechte Rand, beim Polygon wird der Schnittpunkt mit dem betreffenden Polygon-Segment berechnet, beim Floodfill sucht man, je nach Verfahren, wann ein Pixel entlang der horizontalen Linie die gewünschte Randfarbe hat bzw. wann die aktuelle Hintergrundfarbe sich ändert.

Irgendwie fällt es mir schwer das zu schlucken, denn woher will FloodFill denn wissen womit ein Rechteck gezeichnet wurde?
Das

Code: Alles auswählen

 
  PaintBox1.Canvas.MoveTo(0, 0);
  PaintBox1.Canvas.LineTo(99, 0);
  PaintBox1.Canvas.LineTo(99, 99);
  PaintBox1.Canvas.LineTo(0, 99);
  PaintBox1.Canvas.LineTo(0, 0);
 

ist doch das gleiche wie das

Code: Alles auswählen

 
  PaintBox1.Canvas.Rectangle(0, 0, 99, 99);
 

oder nicht?

Nein. Die Folge von MoveTo/LineTo-Befehlen zeichnet nur den Umriss des Rechtecks, Rectangle füllt es zusätzlich mit der Farbe des aktuellen Brush, wobei das Füllen intern durch Zeichnen horizontaler Linien zwischen 0 und 99 erfolgt.

Bei FloodFill ist der Routine nichts über die Geometrie der zu füllenden Figur bekannt, der Algorithmus beginnt am Startpunkt, läuft nach links, bis ein Pixel in der Randfarbe gefunden wird; dann läuft der Algorithmus nach rechts, bis wieder ein Pixel in der Randfarbe gefunden wird, und es wird eine Linien zwischen dem linken und rechten Randpunkt gezogen. Dasselbe wiederholt sich für alle Pixel in y-Richting. Wobei das noch vereinfacht ist, weil ja jenseits der so festgestellen Randpixel, getrennt durch eine Einbuchtung, weitere zu füllende Gebiete liegen können. Insgesamt ist FloodFill erheblich langsamer als Canvas.Rectangle.

Jole
Beiträge: 116
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von Jole »

@wp_xyz:
Jetzt hab ich es verstanden, bin schon wieder einem Irrtum unterlegen. Ich dachte Rectangle würde (wie bei TP) nur ein Rechteck zeichnen und FillRect ein gefülltes Rechteck. Ich hab jetzt Grad gesehen wer was wie macht. Also, danke für die Erklärungen.

Winni
Beiträge: 195
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.06, fpc 3.04
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von Winni »

Unter Linux/gtk war floodfill lange nicht implementiert. ich weiß nicht, wie der derzeitige Stand ist.

Abhilfe:
1. In der Unit GrapUtil gibt es ein floodfill, das auf jedem Canvas arbeitet, aber langsam ist
.2. Im BGRA-Paket gibt es ein ziemlich schnelles floodfill

Grüße

Jole
Beiträge: 116
Registriert: Fr 4. Jul 2014, 14:39
OS, Lazarus, FPC: Linux
CPU-Target: amd64

Re: FloodFill () Funktioniert unter Linux nur bedingt

Beitrag von Jole »

Winni hat geschrieben:Unter Linux/gtk war floodfill lange nicht implementiert. ich weiß nicht, wie der derzeitige Stand ist.

Wie wir festgestellt haben ist FloodFill nur als dummy vorhanden.
Jetzt hab ich zufällig im Delphipraxis Forum gesehen das da Gestern einer eine ähnliche frage gestellt hat, vielleicht interessiert das ja jemand.

Antworten