prev up inhalt next


4.1 Universelle Füll-Verfahren

Universelle Füllverfahren stützen sich auf die Nachbarschaft eines Pixels. Abbildung 4.1 zeigt zwei Varianten.



Nachbarn zu im 4-way-stepping

Nachbarn zu im 8-way-stepping
Nachbarschaften bei universellen Füllverfahren
Ausgehend vom Startpunkt ( x,y ) werden so lange die 4-way-stepping-Nachbarn gefärbt, bis die Umgrenzung erreicht ist.

Vorteil:
beliebige Umrandung möglich
Nachteil:
hoher Rechen- und Speicherbedarf

Obacht:

Gebiete, die nur durch 8-way-stepping erreicht werden können, werden beim Füllen mit 4-way-stepping ``vergessen'', wird hingegen die Nachbarschaft über 8-way-stepping definiert, so ``läuft die Farbe aus''.

Bild 4.1 zeigt beide Effekte.



Unerreichtes Gebiet beim 4-way-stepping

Farbauslauf beim 8-way-stepping
Probleme bei universellen Füllverfahren
Benötigt werden
    boolean get_pixel (            // liefert true, wenn Pixel p
                       Point p)    // die Vordergrundfarbe hat

und

    boolean range_ok (             // liefert false, wenn Pixel p
                       Point p)    // ausserhalb des Bildbereichs

Der Nachteil der sehr ineffizienten Methode boundary_fill liegt darin, daß für jedes Pixel innerhalb der Begrenzungskurve(n) (mit Ausnahme der Randpixel des inneren Gebiets) der Algorithmus viermal aufgerufen wird. Dadurch werden die Pixel mehrfach auf dem Stapel abgelegt.

Eine Beschleunigung des Verfahrens läßt sich dadurch erreichen, daß auf dem Stapel jeweils Repräsentanten für noch zu füllende Zeilen abgelegt werden, d.h. nach dem Einfärben einer kompletten horizontalen Linie werden von den unmittelbar angrenzenden Zeilen solche Punkte auf den Stapel gelegt, die noch nicht gefüllt worden sind und die unmittelbar links von einer Begrenzung liegen.

/*************************************************************************************/
/*                                                                                   */
/*                   Fuellen einer durch Vordergrundfarbe umrandeten Flaeche         */
/*                                                                                   */
/*************************************************************************************/

private void boundary_fill(             // setzt alle Nicht-Vordergrund-Pixel
                           Point p)     // beginnend bei Position p auf Vordergrund
{
        if ( range_ok(p) && !get_pixel(p) ) {    // falls p keine Vordergrundfarbe hat

                set_pixel(p);                    // setze Vordergrundfarbe

                boundary_fill( new Point(p.x+1, p.y   ));  // 4-way stepping
                boundary_fill( new Point(p.x,   p.y+1 ));
                boundary_fill( new Point(p.x-1, p.y   ));
                boundary_fill( new Point(p.x,   p.y-1 ));

        }
}

/*************************************************************************************/
/*                                                                                   */
/*                   Leeren einer durch Vordergrundfarbe definierten Flaeche         */
/*                                                                                   */
/*************************************************************************************/

private void boundary_empty(            // setzt alle Vordergrund-Pixel beginnend 
                            Point p)    // bei Position p auf Hintergrundfarbe
{
        if ( range_ok(p) && get_pixel(p) ) {    // falls p Vordergrundfarbe hat

                del_pixel(p);                   // setze Hintergrundfarbe

                boundary_empty( new Point( p.x+1, p.y   ));  // 8-way-stepping
                boundary_empty( new Point( p.x+1, p.y+1 ));
                boundary_empty( new Point( p.x,   p.y+1 ));
                boundary_empty( new Point( p.x-1, p.y+1 ));
                boundary_empty( new Point( p.x-1, p.y   ));
                boundary_empty( new Point( p.x-1, p.y-1 ));
                boundary_empty( new Point( p.x,   p.y-1 ));
                boundary_empty( new Point( p.x+1, p.y-1 ));

        }
}
	

/*****************************************************************************/
/*                                                                           */
/*   linienweises Fuellen einer durch Vordergrundfarbe umrandeten Flaeche    */
/*                                                                           */
/*****************************************************************************/

  private void fillRowByRow(int x, int y, Graphics g) {
    int lg;                                      // nicht gesetzte Pixel ganz
    int rg;                                      // links/rechts in dieser Z.
    Punkt hilf;                                  // Hilfpunkt
    int px = x;                                  // lokale Kopie

    while(!isPixelSet(x, y)) {                   // Solange Pixel ungesetzt
      setPixelInBuf(x, y);                       // Pixel merken und setzen
      hilf = new Punkt(x, y);
      hilf.paint(g);
      x--;                                       // naechstes Pixel links
    }
    lg = x+1;                                    // 1 zu weit gelaufen

    x = px + 1;                                  // da (px,y) schon gesetzt

    while(!isPixelSet(x, y)) {                   // Solange Pixel ungesetzt
      setPixelInBuf(x, y);                       // Pixel merken und setzen
      hilf = new Punkt(x, y);
      hilf.paint(g);
      x++;                                       // naechstes Pixel rechts
    }
    rg = x-1;                                    // 1 zu weit gelaufen

    for(int pos = rg; pos >= lg; pos--) {        // von rechts nach links
      if(!isPixelSet(pos, y - 1)) {              // falls Pixel in Reihe ueber 
                                                 // dieser nicht gesetzt:
        fillRowByRow(pos,y-1, g);                // Repraesentant! neuer Aufruf
      }
      if(!isPixelSet(pos, y + 1)) {              // falls Pixel in Reihe unter 
                                                 // dieser nicht gesetzt:
        fillRowByRow(pos,y+1, g);                // Repraesentant! neuer Aufruf
      }
    }
    return;
  }
	


prev up inhalt next