<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Floodfill</id>
	<title>Floodfill - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Floodfill"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Floodfill&amp;action=history"/>
	<updated>2026-06-02T19:41:24Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Floodfill&amp;diff=282938&amp;oldid=prev</id>
		<title>imported&gt;Invisigoth67: typo</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Floodfill&amp;diff=282938&amp;oldid=prev"/>
		<updated>2024-03-02T09:08:27Z</updated>

		<summary type="html">&lt;p&gt;typo&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Floodfill&amp;#039;&amp;#039;&amp;#039; bzw. &amp;#039;&amp;#039;&amp;#039;Flutfüllung&amp;#039;&amp;#039;&amp;#039; ist ein Begriff aus der [[Computergrafik]]. Es ist ein einfacher [[Algorithmus]], um Flächen zusammenhängender [[Pixel]] einer Farbe in einem digitalen Bild zu erfassen und mit einer neuen Farbe zu füllen.&lt;br /&gt;
&lt;br /&gt;
Ausgehend von einem Pixel innerhalb der Fläche werden jeweils dessen Nachbarpixel darauf getestet, ob diese Nachbarpixel auch die alte Farbe enthalten. Jedes gefundene Pixel mit der alten Farbe wird dabei sofort durch die neue Farbe ersetzt.&lt;br /&gt;
&lt;br /&gt;
== Rekursive  Implementierung ==&lt;br /&gt;
Es gibt zwei Varianten der [[Rekursive Programmierung|rekursiven]] Implementierung.&lt;br /&gt;
&lt;br /&gt;
=== 4-connected oder 4-Neighbour ===&lt;br /&gt;
[[Datei:Recursive Flood Fill 4 (aka).gif|rechts|Schema]]&lt;br /&gt;
Es werden jeweils die 4 benachbarten [[Pixel]] unten, links, oben und rechts vom Ausgangspunkt untersucht. Der Koordinatenursprung ist die Ecke links oben.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def fill4(x, y, alteFarbe, neueFarbe):&lt;br /&gt;
    if getPixel(x, y) == alteFarbe:&lt;br /&gt;
        setPixel(x, y, neueFarbe)&lt;br /&gt;
        fill4(x, y + 1, alteFarbe, neueFarbe)  # unten&lt;br /&gt;
        fill4(x, y - 1, alteFarbe, neueFarbe)  # oben&lt;br /&gt;
        fill4(x + 1, y, alteFarbe, neueFarbe)  # rechts&lt;br /&gt;
        fill4(x - 1, y, alteFarbe, neueFarbe)  # links&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== 8-connected oder 8-Neighbour ===&lt;br /&gt;
[[Datei:Recursive Flood Fill 8 (aka).gif|rechts|Schema]]&lt;br /&gt;
Es werden jeweils die 8 benachbarten [[Pixel]] oben, unten, links, rechts, oben-links, oben-rechts, unten-links und unten-rechts vom Ausgangspunkt untersucht. Der Koordinatenursprung ist die Ecke links oben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def fill8(x, y, alteFarbe, neueFarbe):&lt;br /&gt;
    if getPixel(x, y) == alteFarbe:&lt;br /&gt;
        setPixel(x, y, neueFarbe)&lt;br /&gt;
        fill8(x    , y + 1, alteFarbe, neueFarbe)  # unten&lt;br /&gt;
        fill8(x    , y - 1, alteFarbe, neueFarbe)  # oben&lt;br /&gt;
        fill8(x + 1, y,     alteFarbe, neueFarbe)  # rechts&lt;br /&gt;
        fill8(x - 1, y,     alteFarbe, neueFarbe)  # links&lt;br /&gt;
        fill8(x + 1, y + 1, alteFarbe, neueFarbe)  # rechts unten&lt;br /&gt;
        fill8(x + 1, y - 1, alteFarbe, neueFarbe)  # rechts oben&lt;br /&gt;
        fill8(x - 1, y + 1, alteFarbe, neueFarbe)  # links unten&lt;br /&gt;
        fill8(x - 1, y - 1, alteFarbe, neueFarbe)  # links oben&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Bei gleichen Ausgangsbedingungen füllt die &amp;#039;&amp;#039;8-connected&amp;#039;&amp;#039;-Variante üblicherweise einen größeren Bereich als die &amp;#039;&amp;#039;4-connected&amp;#039;&amp;#039;-Variante, da sie „durch feine Ritzen kriecht“. Je nach Anwendungsfall kann dies gewünscht sein oder auch nicht.&lt;br /&gt;
&lt;br /&gt;
Der Algorithmus in der [[Rekursive Programmierung|rekursiven]] Form ist zwar einfach zu formulieren und zu verstehen, eignet sich jedoch nur bedingt für nicht-triviale Anwendungen. Der Algorithmus ist überaus rekursiv. Daher besteht ein hohes Risiko, dass der Algorithmus zu einem [[Stack Overflow]] führt. Ebenso benötigen die möglichen vielen Stack-Operationen durch die Rekursionen im Vergleich zu den eigentlichen Operationen des Algorithmus relativ viel Zeit.&lt;br /&gt;
&lt;br /&gt;
Nicht zuletzt sind viele Rekursionsaufrufe des Algorithmus unnötig, da dabei unnötigerweise [[Pixel]] getestet werden, die kurz zuvor bereits auf die neue Farbe gesetzt wurden. Jede [[Rekursion]] trifft mindestens auf ein solches Pixel, jenes Pixel, welches gerade im darüberliegenden Rekursionslevel markiert wurde.&lt;br /&gt;
&lt;br /&gt;
== Iterative Implementierung ==&lt;br /&gt;
&lt;br /&gt;
=== Programmierung ===&lt;br /&gt;
Mit Hilfe einer [[Warteschlange (Datenstruktur)|Warteschlange]], eines [[Stapelspeicher]]s oder einer ähnlichen [[Datenstruktur]] ist auch eine [[Iteration|iterative]] Implementierung möglich. Dabei werden die Nachbarpixel-[[Koordinaten]] gespeichert und dann nacheinander abgearbeitet. Die Reihenfolge, in der die Koordinaten aus der Datenstruktur ausgelesen werden, spielt dabei keine Rolle. Durch das hohe Risiko eines [[Stack Overflow]] bei der rekursiven Implementierung ist die iterative Version in der Regel die bessere Wahl zur Implementierung des Verfahrens.&lt;br /&gt;
&lt;br /&gt;
==== C# ====&lt;br /&gt;
Das folgende [[Computerprogramm|Programm]] in der [[Programmiersprache]] [[C-Sharp|C#]] verwendet zwei verschachtelte [[While-Schleife|while-Schleifen]] für eine [[Breitensuche]] der [[Pixel]] mit derselben Farbe.&amp;lt;ref&amp;gt;Rosetta Code: [https://rosettacode.org/wiki/Bitmap/Flood_fill Bitmap/Flood fill]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;GeeksforGeeks: [https://www.geeksforgeeks.org/flood-fill-algorithm-implement-fill-paint/ Flood fill Algorithm]&amp;lt;/ref&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c#&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Drawing;&lt;br /&gt;
&lt;br /&gt;
namespace FloodFill&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
		// Diese Methode gibt true zurück, wenn die beiden Farben gleich sind, sonst false&lt;br /&gt;
		private static bool ColorMatch(Color replacementColor, Color targetColor)&lt;br /&gt;
		{&lt;br /&gt;
			return replacementColor.ToArgb() == targetColor.ToArgb();&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		// Diese Methode füllt alle zusammenhängenden Pixel, die dieselbe Farbe wie das Startpixel haben, mit der neuen Farbe&lt;br /&gt;
		private static void FloodFill(Bitmap bitmap, Point point, Color replacementColor)&lt;br /&gt;
		{&lt;br /&gt;
			Color targetColor = bitmap.GetPixel(point.X, point.Y); // Speichert die Farbe des Startpixels&lt;br /&gt;
			Queue&amp;lt;Point&amp;gt; queue = new Queue&amp;lt;Point&amp;gt;(); // Warteschlange der Pixel für die Breitensuche&lt;br /&gt;
			queue.Enqueue(point); // Fügt das Startpixel der Warteschlange hinzu&lt;br /&gt;
			while (queue.Count != 0) // So lange die Warteschlange nicht leer ist&lt;br /&gt;
			{&lt;br /&gt;
				Point point1 = queue.Dequeue(); // Entfernt das erste Pixel aus der Warteschlange&lt;br /&gt;
				if (!ColorMatch(bitmap.GetPixel(point1.X, point1.Y), targetColor)) // Wenn die Farbe des aktuellen Pixels gleich dem Startpixel ist, wird die nächste Iteration der äußeren while-Schleife ausgeführt&lt;br /&gt;
				{&lt;br /&gt;
					continue;&lt;br /&gt;
				}&lt;br /&gt;
				Point point2 = new Point(point1.X + 1, point1.Y); // Speichert das Pixel rechts vom aktuellen Pixel&lt;br /&gt;
				while (point1.X &amp;gt;= 0 &amp;amp;&amp;amp; ColorMatch(bitmap.GetPixel(point1.X, point1.Y), targetColor)) // So lange das aktuelle Pixel nicht links vom Rand ist und die Farbe des Startpixels hat&lt;br /&gt;
				{&lt;br /&gt;
					bitmap.SetPixel(point1.X, point1.Y, replacementColor); // Setzt das aktuelle Pixel auf die neue Farbe&lt;br /&gt;
					if (point1.Y &amp;gt; 0 &amp;amp;&amp;amp; ColorMatch(bitmap.GetPixel(point1.X, point1.Y - 1), targetColor)) // Wenn das aktuelle Pixel nicht am linken Rand ist und die Farbe des Startpixels hat&lt;br /&gt;
					{&lt;br /&gt;
						queue.Enqueue(new Point(point1.X, point1.Y - 1)); // Fügt das Pixel über dem aktuellen Pixel der Warteschlange hinzu&lt;br /&gt;
					}&lt;br /&gt;
					if (point1.Y &amp;lt; bitmap.Height - 1 &amp;amp;&amp;amp; ColorMatch(bitmap.GetPixel(point1.X, point1.Y + 1), targetColor)) // Wenn das aktuelle Pixel nicht am rechten Rand ist und die Farbe des Startpixels hat&lt;br /&gt;
					{&lt;br /&gt;
						queue.Enqueue(new Point(point1.X, point1.Y + 1)); // Fügt das Pixel unter dem aktuellen Pixel der Warteschlange hinzu&lt;br /&gt;
					}&lt;br /&gt;
					point1.X--; // Verschiebt das aktuelle Pixel um 1 nach links&lt;br /&gt;
				}&lt;br /&gt;
				// Die folgende while-Schleife wiederholt den Ablauf mit dem Pixel rechts vom aktuellen Pixel&lt;br /&gt;
				while (point2.X &amp;lt;= bitmap.Width - 1 &amp;amp;&amp;amp; ColorMatch(bitmap.GetPixel(point2.X, point2.Y), targetColor))&lt;br /&gt;
				{&lt;br /&gt;
					bitmap.SetPixel(point2.X, point2.Y, replacementColor);&lt;br /&gt;
					if (point2.Y &amp;gt; 0 &amp;amp;&amp;amp; ColorMatch(bitmap.GetPixel(point2.X, point2.Y - 1), targetColor))&lt;br /&gt;
					{&lt;br /&gt;
						queue.Enqueue(new Point(point2.X, point2.Y - 1));&lt;br /&gt;
					}&lt;br /&gt;
					if (point2.Y &amp;lt; bitmap.Height - 1 &amp;amp;&amp;amp; ColorMatch(bitmap.GetPixel(point2.X, point2.Y + 1), targetColor))&lt;br /&gt;
					{&lt;br /&gt;
						queue.Enqueue(new Point(point2.X, point2.Y + 1));&lt;br /&gt;
					}&lt;br /&gt;
					point2.X++; // Verschiebt das aktuelle Pixel um 1 nach rechts&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		// Hauptmethode, die das Programm ausführt&lt;br /&gt;
		public static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			Bitmap bitmap = new Bitmap(&amp;quot;UnfilledCircle.png&amp;quot;); // Weist den Inhalt der Bilddatei mit dem angegebenen Dateinamen der Variablen der Klasse Bitmap hinzu&lt;br /&gt;
			FloodFill(bitmap, new Point(200, 200), Color.Red); // Aufruf der Methode mit den Parametern für Startpixel und Farbe&lt;br /&gt;
			bitmap.Save(&amp;quot;FilledCircle.png&amp;quot;); // Speichert das geänderte Bitmap als Bilddatei mit dem angegebenen Dateinamen&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Python ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def fill4(x, y, alteFarbe, neueFarbe):&lt;br /&gt;
    stack.push(x, y)&lt;br /&gt;
    while stack.isNotEmpty():&lt;br /&gt;
        (x, y) = stack.pop()&lt;br /&gt;
        if getPixel(x, y) == alteFarbe:&lt;br /&gt;
            setPixel(x, y, neueFarbe)&lt;br /&gt;
            stack.push(x, y + 1)&lt;br /&gt;
            stack.push(x, y - 1)&lt;br /&gt;
            stack.push(x + 1, y)&lt;br /&gt;
            stack.push(x - 1, y)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Dieses [[Iterative Programmierung|iterative]] Beispiel entspricht dem rekursiven Algorithmus mit vier Nachbarn. Derjenige mit acht Nachbarn wird entsprechend analog implementiert.&lt;br /&gt;
&lt;br /&gt;
Anstatt auf dem [[Stapelspeicher|Stack]] die als Nächstes zu testenden Positionen zu speichern, ist es möglich, die vorherigen Positionen und Richtungen zu speichern. Der Stack enthält dadurch nur den Pfad zur derzeitigen Position, was den Algorithmus speichereffizienter macht.&amp;lt;ref&amp;gt;[https://github.com/minetest/minetest/blob/f7c7353a9a9446a2fb6b3b0cb24deec0851d7291/builtin/game/falling.lua#L401 Tiefensuche von zusammenhängenden Nodes in] [[Minetest]]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Teiliterative Implementierung ==&lt;br /&gt;
Bei teiliterativer Implementierung besteht der Algorithmus aus einem [[Iterative Programmierung|iterativen]] Teil, der immer weiterläuft und sich immer in eine bestimmte Richtung wendet, zum Beispiel immer linksherum. Wenn der iterative Teil keine [[Pixel]] mehr zum Einfärben findet, wird der [[Rekursive Programmierung|rekursive]] Teil gestartet, der nun deutlich weniger tief in die [[Rekursion]] geht. Somit ist ein [[Stack Overflow]] weniger wahrscheinlich.&lt;br /&gt;
&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Computergrafik]]&lt;br /&gt;
[[Kategorie:Algorithmus (Computergrafik)]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Invisigoth67</name></author>
	</entry>
</feed>