# füllen



## VdA (17. Dez 2006)

Ihr kennt das bestimmt von Paint:






 :wink: 
nun habe ich ein BufferedImage, auf dem schon ein paar Striche und Kreise etc. sind, und ich will von einem Punkt
ausgehend alles was die selbe farbe hat mit einer neuen Farbe füllen zB das innere eines kreises mit rot.

Halt wie in Paint :wink: 
Hab aber keine Ahnung wie ich die Farben der Pixel vergleichen kann.
Weiß jemand wie das geht?


----------



## VdA (18. Dez 2006)

gibt es eine Methode die mir ein Color Objekt von einem Punkt xy gibt?


----------



## SlaterB (18. Dez 2006)

für die Klasse BufferedImage gibts doch

 int 	getRGB(int x, int y)
          Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace.


kanntest du die nicht?


----------



## VdA (19. Dez 2006)

doch aber:


> int 	getRGB(int x, int y)
> Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace.


die liefert ein int und kein Color-Objekt


----------



## The_S (19. Dez 2006)

Aber daraus kannst du die Farben extrahieren. Bzw alternativ einfach die Zahl einem neuen Color Objekt im Konstruktor übergeben.


----------



## VdA (19. Dez 2006)

thx


----------



## SlaterB (19. Dez 2006)

aus int ein Color geht sofort (evtl. einmalig Code zu erstellen, Hobbit weiß da Rat  ),
und dauert dann in der Ausführungszeit nicht entscheidend länger als direkt ein Color-Objekt,

aber stell dir mal vor es würde standardmäßig Color kommen,
bei der Verarbeitung von Millionen von Pixeln soviele langsame Objekte..,

beide Operationen zur Verfügung zu haben wäre natürlich das Beste


----------



## VdA (20. Dez 2006)

danke!  
da funzt jetzt nur leider hat sich jetzt ein neues problem aufgetan:




Ich will da 3eck ausfüllen aber er fülllt nur die Pixel die oben schwarz sind
das ist mein Code:

```
void fülle(Graphics g, MouseEvent evt, BufferedImage bild)
	{
		//hier füllt er flächen aus
		g.setColor(CurrentColor.current_color);
		Color ausgangs_farbe = null;
		try{
		ausgangs_farbe =new Color(bild.getRGB(evt.getX(), evt.getY()));
		}catch(java.lang.ArrayIndexOutOfBoundsException e){}
		System.out.println(ausgangs_farbe);
		
		
		for(int x=evt.getX();x<this.getSize().width && x>0;x-- )
		{
			Color farbe;
			if(ausgangs_farbe.equals(farbe=new Color(bild.getRGB(x, evt.getY()))))
			{
				for(int y=evt.getY();y<this.getSize().height && y>0;y-- )
				{
					
					if(ausgangs_farbe.equals(farbe=new Color(bild.getRGB(x, y))))
					{
						g.drawLine(x, y, x, y);
					}
					else{
						System.out.println("jetzt");
						break;
					}
					
				}
				for(int y=evt.getY();y<this.getSize().height && y>0;y++ )
				{
					
					if(ausgangs_farbe.equals(farbe=new Color(bild.getRGB(x, y))))
					{
						g.drawLine(x, y, x, y);
					}
					else{
						System.out.println("jetzt");
						break;
					}
				}
			}
			else{
				System.out.println("jetzt");
				break;
			}
		}

		for(int x=evt.getX();x<this.getSize().width && x>0;x++ )
		{
			Color farbe;
			if(ausgangs_farbe.equals(farbe=new Color(bild.getRGB(x, evt.getY()))))
			{
				for(int y=evt.getY();y<this.getSize().height && y>0;y-- )
				{
					
					if(ausgangs_farbe.equals(farbe=new Color(bild.getRGB(x, y))))
					{
						g.drawLine(x, y, x, y);
					}
					else{
						System.out.println("jetzt");
						break;
					}
					
				}
				for(int y=evt.getY();y<this.getSize().height && y>0;y++ )
				{
					
					if(ausgangs_farbe.equals(farbe=new Color(bild.getRGB(x, y))))
					{
						g.drawLine(x, y, x, y);
					}
					else{
						System.out.println("jetzt");
						break;
					}
				}
			}
			else{
				System.out.println("jetzt");
				break;
			}
		}
		
		

		
	}
```
Ich glaub ich müsste irgendwie das ganze von Grund auf anders angehen mir fällt nur im moment nicht ein wie.
ich gucke immer von der x-Achse ausgehen ob obe und unten alles frei is und spring ein weiter.
Weiß jemand rat?    :bahnhof:


----------



## Illuvatar (21. Dez 2006)

Also ich würde das generell etwas anders angehen, nämlich rekursiv. Pseudocode als Denkanstoß:


```
füllen (Pixel p, Color füllFarbe)
{
  Color c = p.farbe;
  p.farbe = füllFarbe;
  for (Pixel otherPixel : p.umliegendePixel){
    if (otherPixel.farbe == c) füllen(otherPixel, füllFarbe);
  }
}
```

Edit: Ist der Fred absichtlich abgehakt?


----------



## VdA (21. Dez 2006)

> ```
> füllen (Pixel p, Color füllFarbe)
> {
> Color c = p.farbe;
> ...


führt das nicht dazu das er die Pixel immer wieder nachguckt und 100%Cpu verursacht?


----------



## Illuvatar (21. Dez 2006)

IMO nicht, da die Rekursion ja abbricht, wenn der andere Pixel nicht die Farbe hat, wie der geklickte. Und die Pixelfarben werden immer gleich geändert.


----------



## VdA (21. Dez 2006)

ja gut das kling gut


----------



## VdA (23. Dez 2006)

jetzt habe ich ein anderes problem:
er fülllt nur die pixel die unter dem angeklickten Punkt liegen
hier mein Code:

```
public void fülle(Graphics g, Point pixel, BufferedImage bild, ZeichenBlock block)
	{
		//hier füllt er flächen aus
		System.out.println("füllen");

		try{
			Color ausgangs_farbe = new Color(bild.getRGB(pixel.x, pixel.y)); 
			Color füllFarbe= g.getColor();
			
			Point[] umliegende_Pixel=getUmliegendePixel(pixel, bild, ausgangs_farbe);
			try{
			for(int i=0;i<umliegende_Pixel.length; i++ )
			{
				fülle(g, umliegende_Pixel[i], bild, block);
			}
			}catch(java.lang.StackOverflowError e){}
			g.drawLine(pixel.x, pixel.y, pixel.x, pixel.y);
		}catch(java.lang.ArrayIndexOutOfBoundsException e){System.err.println(e);}
		//System.out.println(ausgangs_farbe);
		
		
		

		
	}
	Point[] getUmliegendePixel(Point pixel, BufferedImage bild, Color ausgangs_farbe)
	{
		Point[] last_Points=new Point[0];
		Point[] Points=new Point[1];
		if(new Color(bild.getRGB(pixel.x-1, pixel.y)).equals(ausgangs_farbe) )
		{
			try{
			Points = new Point[last_Points.length+1];
			}catch(java.lang.NullPointerException e){}
			for(int i=0;i< Points.length-1;i++)
			{
				Points[i] = last_Points[i];
			}
			Points[Points.length-1]=new Point(pixel.x-1, pixel.y);
		}
		if(new Color(bild.getRGB(pixel.x+1, pixel.y)).equals(ausgangs_farbe) )
		{
			try{
			Points = new Point[last_Points.length+1];
			}catch(java.lang.NullPointerException e){}
			for(int i=0;i< Points.length-1;i++)
			{
				Points[i] = last_Points[i];
			}
			Points[Points.length-1]=new Point(pixel.x+1, pixel.y);
		}
		if(new Color(bild.getRGB(pixel.x, pixel.y-1)).equals(ausgangs_farbe) )
		{
			try{
			Points = new Point[last_Points.length+1];
			}catch(java.lang.NullPointerException e){}
			for(int i=0;i< Points.length-1;i++)
			{
				Points[i] = last_Points[i];
			}
			Points[Points.length-1]=new Point(pixel.x, pixel.y-1);
		}
		if(new Color(bild.getRGB(pixel.x, pixel.y+1)).equals(ausgangs_farbe) )
		{
			try{
			Points = new Point[last_Points.length+1];
			}catch(java.lang.NullPointerException e){}
			for(int i=0;i< Points.length-1;i++)
			{
				Points[i] = last_Points[i];
			}
			Points[Points.length-1]=new Point(pixel.x, pixel.y+1);
		}
		
		return Points;	
	}
```
Und wieder mal hab ich keine Ahnung :bahnhof:  :autsch:


----------



## SlaterB (25. Dez 2006)

falls das noch aktuell ist, schreibe ab und zu mal ein 'Erinnerungspost',
solche anschaulichen Knobeleien sind ja spannend 
(auch wenns wahrscheinlich ganz simple Fehler sind),

ich persönlich habe im Moment aber keine Zeit (Weihnachten)


----------



## Illuvatar (25. Dez 2006)

Da ich grad weihnachtlich gestimmt bin  hab ich dir daraus mal einen funktionierenden Code gebaut.


```
public void fülle(Graphics g, Point pixel, BufferedImage bild)
   {
      Color ausgangsFarbe = new Color(bild.getRGB(pixel.x, pixel.y));
      bild.setRGB(pixel.x, pixel.y, g.getColor().getRGB());

      Point[] umliegendePixel = getUmliegendePixel(pixel, bild, ausgangsFarbe.getRGB());
      try {
          for(Point newPixel : umliegendePixel)
          {
             if (bild.getRGB(newPixel.x, newPixel.y) == ausgangsFarbe.getRGB()){
                     fülle(g, newPixel, bild);
             }
          }
      } catch (StackOverflowError e) {
          //do nothing
      }
   }
   Point[] getUmliegendePixel(Point pixel, BufferedImage bild, int rgb)
   {
      ArrayList<Point> points = new ArrayList<Point>();
      if (pixel.x > 0){
        points.add (new Point(pixel.x - 1, pixel.y));
      }
      if ((pixel.x + 1) < bild.getWidth()){
        points.add (new Point(pixel.x + 1, pixel.y));
      }
      if (pixel.y > 0){
        points.add (new Point(pixel.x, pixel.y - 1));
      }
      if ((pixel.y + 1) < bild.getHeight()){
        points.add (new Point(pixel.x, pixel.y + 1));
      }
      return points.toArray(new Point[]{});
   }
```

Allerdings benötigt diese Methode einen viel größeren Stack, als ich es bedacht hatte. Kleinere Flächen lassen sich ausfüllen, große resultieren in einem StackOverflow (den ich zwar ignorieren lasse, dadurch funktioniert das aber nicht mehr richtig). Wenn man das Programm z.B. mit "-ss15m -oss60m" startet, funktioniert das auch für größere Flächen (bis zu, sagen wir, 400*400px²) prima - aber 75MB Stack ist doch auch Performancemäßig nicht gerade toll...
Dann bleibt für dich ja doch noch was zu tun :bae: Du müsstest das jetzt eben noch irgendwie iterativ lösen.


----------



## VdA (26. Dez 2006)

leider füllt er im Moment nur einen Punkt, den auf den Man geklickt hat  
aber was bringt eigentlich

```
for(Point newPixel : umliegendePixel)
```
mir ist nicht ganz klar wofür das ":" steht :bahnhof:


----------



## Illuvatar (27. Dez 2006)

foreach-Schleife, wurde neu in Java5 eingeführt (such einfach mal danach)


----------



## VdA (27. Dez 2006)

gut habs verstanden  
nur leider wird bei mir immer nur ein Punkt ausgefüllt


----------



## Illuvatar (27. Dez 2006)

Mit welchem Code? Dem von mir? Zeig mal dein ganzes Programm.


----------



## VdA (28. Dez 2006)

öhm das ganze Programm ist um die 62 kilo bytes groß möchtest du das wirklich alles sehen?


----------



## VdA (28. Dez 2006)

ach egal ich poste einfach mal den link:
Mein Malprogramm
vllt findest du den Fehler :?


[Edit:]Wenn das Fertig ist werd ich das sowieso allen die es brauchen zugänglich machen da ich denke das Microsoft-Paint in den Meisten fällen nicht ausreichend ist aber irgenwelche Programmme von sonstwoher zu Umfangreich sind
vor allem soll aus diesem Malprogramm noch mehr werden, was ich dann wiederum nicht veröffenlichen werde. :wink:


----------



## Illuvatar (28. Dez 2006)

404. Aber wenn das so groß ist, mach doch eh vielleicht besser ein KSKB


----------



## VdA (30. Dez 2006)

gut werd ich, aber nicht jetzt jetzt fahr ich ersma in Urlaub


----------

