# Aufteilung eines Bildes in JLabel



## pl4gu33 (5. Okt 2011)

hey,... ich habe mal etwas Code für euch, wo ich nicht weiss, ob man ihn besser machen könnte 
also es geht darum ich lade ein Bild und zerschneide es in mehrere Teile, die Teile werden nach und nach aufgedeckt.... ich hab dies realisiert, in dem ich einem JLabel ein DisableIcon gegeben habe und diese dann nach und nach Enable.... ist der Ansatz so okay? oder geht es besser ? ,... bin für Vorschläge gern zu haben 

wundert euch nicht über die Variablenbezeichnung ich will das später noch alles etwas dynamischer machen und die Variablen "m..." werden dann noch Attribute der Klasse, die bennen ich immer mit m klein für Member  darum hab ich gerade erstmal nur zum Testen alles in die Methode gepackt  .... aber es geht mir gerade erstmal nur um die Art, wie ich den Cut und die Anzeige realisiert habe


```
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.*;

public class BildPanel extends JPanel{	
	private static final long serialVersionUID = 1L;	

	public BildPanel(){
		this.setLayout(new FlowLayout());
		
	}
	
	@SuppressWarnings("deprecation")
	public void paintIt(){				
		File date = new File("Sonnenuntergang.jpg" );
		ArrayList<JLabel> mLabelList=new ArrayList<JLabel>();
		
		try {					
			int laenge=0;
			int breite=0;			
			
			//Erstellen Disable / Enable BufferedImages			
			BufferedImage mImageDisable=new BufferedImage(100,100,BufferedImage.TYPE_INT_ARGB);
			BufferedImage mImage = ImageIO.read( date );			
			
			//Zerschneiden der Bilder und Aufteilen in Label
			for(int i=0;i<mImage.getHeight();i++){
				//Abfrage, sodass man den Rand nicht überschreitet
				if((i+breite)>mImage.getHeight()){
					breite=mImage.getHeight()-i;
				}else{					
					breite=100;
				}				
				for(int j=0;j<mImage.getWidth();j++){
					//Abfrage, sodass man den Rand nicht überschreitet
					if((j+laenge)>mImage.getWidth()){
						laenge=mImage.getWidth()-j;
					}else{					
						laenge=100;
					}		
					//Erstellen des Labels und sofortiges Disablen mit zuweisen der ICONs
					JLabel lbl=new JLabel(new ImageIcon(mImage.getSubimage(j,i,laenge,breite)));
					lbl.setDisabledIcon(new ImageIcon(mImageDisable));
					lbl.disable();
					lbl.setBorder(BorderFactory.createLineBorder(Color.black));
					lbl.repaint();					
					this.add(lbl);
					mLabelList.add(lbl);
					j=j+laenge;
				}				
				i=i+breite;					
			}			
			this.validate();
			
			Thread.sleep(5000);
			
			for(int i=0;i<mLabelList.size();i++){			
				Thread.sleep(1000);		
				mLabelList.get(i).enable();
				mLabelList.get(i).repaint();			
			}	
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}			
		
		
				
	}
	
	  
}
```

hier Bilder wie es aussieht :


----------



## Michael... (5. Okt 2011)

pl4gu33 hat gesagt.:


> hey,... ich habe mal etwas Code für euch, wo ich nicht weiss, ob man ihn besser machen könnte
> also es geht darum ich lade ein Bild und zerschneide es in mehrere Teile, die Teile werden nach und nach aufgedeckt.... ich hab dies realisiert, in dem ich einem JLabel ein DisableIcon gegeben habe und diese dann nach und nach Enable.... ist der Ansatz so okay? oder geht es besser ? ,... bin für Vorschläge gern zu haben


Spricht grundsätzlich nichts dagegen. Ich persönlich tendiere da eher zum selbst zeichnen - ist m.M. flexibler. Wenn es nicht gerade ein Schiebe Puzzle o.ä. werden soll, könnte man sich das Zerteilen des Bildes sparen und es einfach nur mit "Kacheln" bedecken.


----------



## pl4gu33 (7. Okt 2011)

Michael... hat gesagt.:


> Spricht grundsätzlich nichts dagegen. Ich persönlich tendiere da eher zum selbst zeichnen - ist m.M. flexibler. Wenn es nicht gerade ein Schiebe Puzzle o.ä. werden soll, könnte man sich das Zerteilen des Bildes sparen und es einfach nur mit "Kacheln" bedecken.



okay, ich würde diesen Ansatz mit dem selber zeichnen und bedecken besonders interessant finden, wenn ich das Bild in verschiedene Formen zerteilen will (lange Pyramiden,Rechtecke,Kreise etc.). Die Frage ist bloß, wie ich die einzelnen Flächen abspeichere, sodass ich sie nachher wieder freischalten kann... da bin ich mir noch net ganz so sicher, werde die Tage mal schauen


----------



## vanny (7. Okt 2011)

pl4gu33 hat gesagt.:


> Die Frage ist bloß, wie ich die einzelnen Flächen abspeichere, sodass ich sie nachher wieder freischalten kann... da bin ich mir noch net ganz so sicher, werde die Tage mal schauen



Naja, wenn du über dein Bild eine Zeichenfläche legst, die du selbst zeichnest, dann lässt du beim nächsten Zeichnen einfach die entsprechende "Kachel" weg, ist ja nicht so, dass du eine gezeichnete Kachel wegradieren würdest

//Edit: Der Nachteil dieser Methode ist der Verlust, wenn du die Abstände zwischen den einzelnen Kacheln (quasi die Border) nicht berücksichtigst.

Gruß Vanny


----------



## pl4gu33 (8. Okt 2011)

vanny hat gesagt.:


> Naja, wenn du über dein Bild eine Zeichenfläche legst, die du selbst zeichnest, dann lässt du beim nächsten Zeichnen einfach die entsprechende "Kachel" weg, ist ja nicht so, dass du eine gezeichnete Kachel wegradieren würdest
> 
> //Edit: Der Nachteil dieser Methode ist der Verlust, wenn du die Abstände zwischen den einzelnen Kacheln (quasi die Border) nicht berücksichtigst.
> 
> Gruß Vanny



achso, ne ich meinte eigentl. wie ich viele verschiedene Formen automatisch generieren lassen,... bzw. zufällige Flächen einbaue, d.h. also ein Bild kreuz und quer teilen und sich dann die einzelnen Flächen die entstanden sind merken, damit man sie weglassen kann.... meinte das so wie im Bild... und diese Muster werden automatisch generiert und nach und nach aufgedeckt


----------



## vanny (8. Okt 2011)

^^ ... ich bin jetzt einfach mal von deinen ersten Screenshots ausgegangen ... sry

Sowas, wie in deinem Bildanhang hatte ich noch nicht.
Wenn ich mir das aber so anschaue, dann sind das ja alles Linien, die dein Bild in verschiedene Formen teilen.

Wenn mann dann ausrechnet, wo sich diese Linien treffen, hat man die Eckpunkte der Flächen, könnte diese dann in eine Collection ablegen und dann zeichnen lassen.

Ist jetzt mal die erste Idee, vielleicht hilft es dir ja.

Gruß Vanny


----------



## bERt0r (8. Okt 2011)

Bei so komplexen bzw. zufälligen Formen würde ich das Bild nicht zerschneiden sondern einfach z.B per layered Pane das Bild auf eine Ebene legen und darüber die Formen eine Ebene darüber zeichnen. Wenn du dann einen Bereich aufdecken willst wenn du draufklickst, löscht du einfach den Shape der den Klickpunkt beinhaltet.
Mit dem Path2d Shape kannst du ganz gut beliebige Formen basteln.


----------



## pl4gu33 (9. Okt 2011)

bERt0r hat gesagt.:


> Bei so komplexen bzw. zufälligen Formen würde ich das Bild nicht zerschneiden sondern einfach z.B per layered Pane das Bild auf eine Ebene legen und darüber die Formen eine Ebene darüber zeichnen. Wenn du dann einen Bereich aufdecken willst wenn du draufklickst, löscht du einfach den Shape der den Klickpunkt beinhaltet.
> Mit dem Path2d Shape kannst du ganz gut beliebige Formen basteln.



soo hab ichs jetzt auch gemacht, dann brauch ich im Bild nicht mehr rumschnippeln,... nun muss ich mir nur ne Methode überlegen, die mit den zufälligen Elementen wirklich das ganze Bild zukleistert und dann nach und nach mit einem weniger neuzeichnet,.... habs übrigens mit fillPolygon... denke die Methode wird so aussehen, dass er ne Schleife durchgeht und die Polygone je nach Zähler der Schleife anders setzt und dann immer ein Zähler weniger macht beim Repaint(),...


----------



## pl4gu33 (10. Okt 2011)

mm also ich hab nun mal etwas rumprobiert mit Schleifen und Polygonen, dass sie nebeneinander gesetzt werden und das Bild voll machen,... aber irgendwie ist das komisch,... wüsst wer noch ne bessere Lösung das Bild mit Formen zu überdecken.... das Problem sind ja nicht die Formen an sich oder dass das Bild bedeckt ist,... eher ,dass die Formen wirklich Ecke an Ecke, Kante an Kante liegen und nicht wild überlappen und Teile des Bildes womöglich noch zusehen sind, da die Formen willkürlich auf dem Bild liegen und eben nicht aneinander,.... 

also als weitere Idee hätte ich noch eine Klasse die Dreiecke, eine die Trapeze,eine die Parallelogramme und eine die Rechtecke zeichnet. Der Anfang der einen Zeichnung sind immer 2 Punkte der anderen Zeichnung. Problem hierbei ist, wie prüfe ich ob alles abgedeckt ist bzw. ob ich nur die ganze Zeit im Kreis aneinander lege etc.


----------



## Marco13 (10. Okt 2011)

Sollen die "Schnittlinien" wie in dem Bild immer GANZ durch das Bild gehende Linien sein? Dann könnte man die Gesamtfläche als Rectangle2D beschreiben und die einzelnen Teile erstellen, indem die Gesamtfläche und die wegzuschneidenden Teile als Area (Java Platform SE 6) betrachtet und die schneidet. Die einzelnen Teile könnte man dann einfach jeweils mit dem gleichen TexturePaint (Java Platform SE 6) zeichnen. Vielleicht bastle ich da heute abend mal was.... :reflect:


----------



## pl4gu33 (10. Okt 2011)

also vom Grundsatz her ist es egal, ob ich das ganze mit Formen aufbaue also nach und nach verdecke oder einfach Linien kreuz und quer zeichne, müssen halt ne nach Schwierigkeit mehr oder weniger große Flächen entstehen, welche ich dann nach und nach aufdecken kann... das Problem bei Linien, die durch das ganze Bild gehen, ist halt, dass man sehr schnell sehr viele kleine Flächen bekommt, was die Anzahl an Flächen sehr hoch macht ...

(hast du meine Idee die ich dran editiere habe auch gelesen?)

also ich hab allgemein so an 15-40 Formen je nach Schwierigkeit gedacht, um mal ein paar Zahlen zu nennen


----------



## vanny (10. Okt 2011)

Bei der Variante mit den Linien würde ich auf Dreiecke und n-Ecke verzichten, das zu berechnen wird haarig.

Wenn man sich nur auf viereckige Polys beschränkt ist es aber relativ übersichtlich und kann dennoch sehr dynamisch sein.

In diesem Fall "einfach" Breite und Höhe aufteilen, so dass du erstmal die gewünschte Anzahl an Unterteilungen bekommst. Dann mit den Bereichen spielen, welche die Unterteilungen einnehmen dürfen.
(Damit das nich immer aussieht wie ein einfaches Memoryspiel.)
Danach innerhalb dieser Wertebereiche die Trennlinien setzen, ein wenig Mathematik spielen lassen um die Schnittpunkte zu errechnen und dann daraus die Polys erzeugen.

Klingt jetzt wahrscheinlich schlimmer, als es eigentlich ist ^^

Gruß Vanny


----------



## pl4gu33 (9. Feb 2012)

okay ich hab mich nun mal wieder diesem Problem gewitmet und einen Lösungsansatz programmiert, welcher auf den ersten Blick gut funktioniert. Dieser teilt das Bild in mehrere Zeilen auf, wobei jede Zeile ein Maximal und Minimal- Punkt hat, welches beim Viereck die y- Koordinaten darstellen und beim Dreieck Random entschieden wird, ob es nach oben oder unten geht. 

Es werden die neuen Polygone immer direkt an die Alten gezeichnet. 

Die ganzen Bereiche in denen die Polygone vergrößert werden, sind im Moment noch statisch sollen aber später durch variable Werte ersetzt werden. Nur wollte ich mal wissen, was ihr davon bisher haltet bzw. ob ihr Änderungsvorschläge habt. 

ACHTUNG: Wer unter epileptischen Anfälle leidet, könnte /sollte die Farben rausschmeißen, die habe ich nur eingebaut um die Polygone von einander unterscheiden zu können. 

Ich habe es auch etwas mehr Kommentiert, sodass man es leichter versteht ... würde mich über Kritik freuen 

Die IF- Abfragen sind wichtig, dass die richtigen zwei Punkte als letztes stehen, sodass das nächste Polygon daran anknüpfen kann, sonst überlappen sie sich kreuz und quer

DreieckPanel Klasse:

```
public class DreieckPanel extends JPanel{
	/**
	 * 
	 */
	public ArrayList<Polygon> mPolyList;
	private int mHoehe,mBreite,yMIN,yMAX;
	private ArrayList<Color> mColor;	
	private static final long serialVersionUID = 1L;	
	
	public DreieckPanel(int x,int y){
		mPolyList=new ArrayList<Polygon>();
		mColor=new ArrayList<Color>();
		fillColor();
		this.setOpaque(true);
		setBounds(0,0,x,y);
		
		//Die Breite und Höhe werden hier etwas höher gesetzt,
		//sodass Polygone über den Rand gezeichnet werden anstatt
		//dass dort etwas frei bleibt und das letzte Polygon nicht
		//mehr gezeichnet wird
		mHoehe=y+300;
		mBreite=x+300;
		createPolygons();
	}
	
	/***
	 * Methode erstellt alle Formen, diese das Bild verdecken
	 */
	
	private void createPolygons() {
		// TODO Auto-generated method stub
		int yran=0;
		
			//Schleife, welche Stücke für Stück die Zeilen 
			//runterläuft
			while(yran<mHoehe){
				
			//Maximal und Mindest Werte eine Spalte 
			//da die Spalten in Bereiche geteilt sind
			yMIN=yran;
			yMAX=yran+100;
			
			//Setzt das jeweils erste Polygon einer Zeile!
			if(mPolyList.isEmpty()){
				//Reihenfolge der Koordinaten wichtig!
				int[] x={0,0,100};
				int[] y={100,0,100};
				mPolyList.add(new Polygon(x,y));			
			}else{
				int[] x={0,0,100};
				int[] y={yMIN,yMAX,yMIN};
				mPolyList.add(new Polygon(x,y));
			}
			
			//Variable für die größe der X-Koordinate eines Polygons
			int xran=100;		
			
			//Schleife, welche Stücke für Stück die Spalten 
			//füllt. 			
			while(xran<mBreite){	
				//Berechne neues XRAN nach dem Vorgänger, sodass die Polygone
				//sich nicht überlappen
				if(mPolyList.get(mPolyList.size()-1).getLastx()>mPolyList.get(mPolyList.size()-1).getsecondLastx()){
					xran=mPolyList.get(mPolyList.size()-1).getLastx()+100;
				}else{
					xran=mPolyList.get(mPolyList.size()-1).getsecondLastx()+100;
				}
				int random=(int) (Math.random() * (5-3)) + 3;		
				
				//Wählt aus ob ein Dreieck oder Viereck gezeichnet wird
				//Dabei werden als "Anfangs-Koordinaten" immer 2 des letztens
				//Polygons genommen
				if(random==3){
					int xkoordinate=this.getMinMaxY();								
					if((xkoordinate==yMAX) && (yMAX==mPolyList.get(mPolyList.size()-1).getLasty())){
						int[] x={mPolyList.get(mPolyList.size()-1).getLastx(),mPolyList.get(mPolyList.size()-1).getsecondLastx(),xran};
						int[] y={mPolyList.get(mPolyList.size()-1).getLasty(),mPolyList.get(mPolyList.size()-1).getsecondLasty(),xkoordinate};
						mPolyList.add(new Polygon(x,y));
					}else if((xkoordinate==yMAX) && (yMAX==mPolyList.get(mPolyList.size()-1).getsecondLasty())){
						int[] x={mPolyList.get(mPolyList.size()-1).getsecondLastx(),mPolyList.get(mPolyList.size()-1).getLastx(),xran};
						int[] y={mPolyList.get(mPolyList.size()-1).getsecondLasty(),mPolyList.get(mPolyList.size()-1).getLasty(),xkoordinate};
						mPolyList.add(new Polygon(x,y));
					}else if((xkoordinate==yMIN) && (yMIN==mPolyList.get(mPolyList.size()-1).getsecondLasty())){
						int[] x={mPolyList.get(mPolyList.size()-1).getsecondLastx(),mPolyList.get(mPolyList.size()-1).getLastx(),xran};
						int[] y={mPolyList.get(mPolyList.size()-1).getsecondLasty(),mPolyList.get(mPolyList.size()-1).getLasty(),xkoordinate};
						mPolyList.add(new Polygon(x,y));
					}else{						
						int[] x={mPolyList.get(mPolyList.size()-1).getLastx(),mPolyList.get(mPolyList.size()-1).getsecondLastx(),xran};
						int[] y={mPolyList.get(mPolyList.size()-1).getLasty(),mPolyList.get(mPolyList.size()-1).getsecondLasty(),xkoordinate};
						mPolyList.add(new Polygon(x,y));
					}							
				}else{
					if(yMAX==mPolyList.get(mPolyList.size()-1).getLasty()){
						int[] x={mPolyList.get(mPolyList.size()-1).getsecondLastx(),mPolyList.get(mPolyList.size()-1).getLastx(),xran,(int)(20+xran)};
						int[] y={mPolyList.get(mPolyList.size()-1).getsecondLasty(),mPolyList.get(mPolyList.size()-1).getLasty(),yMAX,yMIN};
						mPolyList.add(new Polygon(x,y));	
					}else{						
						int[] x={mPolyList.get(mPolyList.size()-1).getsecondLastx(),mPolyList.get(mPolyList.size()-1).getLastx(),xran,(int)(20+xran)};
						int[] y={mPolyList.get(mPolyList.size()-1).getsecondLasty(),mPolyList.get(mPolyList.size()-1).getLasty(),yMIN,yMAX};
						mPolyList.add(new Polygon(x,y));
					}					
				}			
			}
			yran=yran+100;
		}
		this.repaint();				
	}
	
	/**
	 * Methode entscheidet beim Dreick, ob der "neue" Punkt
	 * nach oben und unten gesetzt wird. Damit dieses dynamischer
	 * wird
	 * 
	 */
	public int getMinMaxY(){
		int random=(int) (Math.random() * (2));			
		if(random==0){			
			return yMIN;
		}		
		return yMAX;
	}
	
	/**
	 * Zeichnet alle Formen über das Bild
	 * 
	 */	
	public void paintComponent(Graphics g){
		if(!mPolyList.isEmpty()){			
			for(int i=0;i<mPolyList.size();i++){
				Collections.shuffle(mColor);
				g.setColor(mColor.get(0));								
				g.fillPolygon(mPolyList.get(i).getX(), mPolyList.get(i).getY(), mPolyList.get(i).getX().length);			
				
			}
		}		
	}
	
	/**
	 *
	 */
	
	private void fillColor() {
		// TODO Auto-generated method stub
		mColor.add(Color.red);
		mColor.add(Color.black);
		mColor.add(Color.yellow);
		mColor.add(Color.white);
		mColor.add(Color.green);
		mColor.add(Color.blue);
	}
	
	
	

}
```

Polygon Klasse:

```
public class Polygon {
	
	private int[] mX,mY;	
	
	public Polygon(int[] x,int[] y){
		mX=x;
		mY=y;		
	}
	

	public int getLastx(){
		return mX[mX.length-1];
		
	}
	
	public int getLasty(){
		return mY[mY.length-1];
		
	}
	
	public int getsecondLastx(){
		return mX[mX.length-2];
		
	}
	
	public int getsecondLasty(){
		return mY[mY.length-2];		
	}
	
	public int[] getY(){
		return mY;
	}
	
	public int[] getX(){
		return mX;
	}
}
```


----------



## bERt0r (10. Feb 2012)

Sieht ja ganz gut aus. Ich habe da einen anderen Ansatz verfolgt: Das Bild rekursiv immer wieder in zwei Hälften schneiden, solange die Polygone über einer gewissen Größe liegen:


----------



## pl4gu33 (10. Feb 2012)

mm okay, sieht ebenfalls gut aus 

aber ich denke ich werde für mich meine Methode weiter ausbauen, sofern keiner etwas daran auszusetzen hat/Mängel findet  oder irgendwelche Verbesserungsvorschläge hat


----------



## bERt0r (14. Feb 2012)

Ich hab an dem Teil noch ein bisschen herumgespielt, weils mich interessiert hat .
Es kann jetzt 3-n-Ecke produzieren, normalerweise sieht man höchstens ein 6-Eck. Ausserdem ist die Maximale Seitenlänge und Fläche der Polygone einstellbar. Der Teilungskoeffizient gibt an, wie weit der Schnittpunkt einer Polygonseite von deren Mittelpunkt abweichen kann. Beim resizen des Fensters passt sich das Bild an und durch anklicken kann man Polygone löschen.


----------

