# Langsames Laden von Bildern und Heap Exception



## Templon (30. Mai 2007)

Hi,
Also ich habe bei meinem kleinen Spiel eine Tile Klasse, in dieser speicher ich Bilder in Form von BufferedImages. Diese Bilder lese ich mit einer Klasse. Nun zu meinen zwei Problemen. Das lesen aus dem Image dauert ewig lange für 50 * 50 Tiles sicher 15 -30 Sekunden. Und wenn ich 100 * 100 Tiles einstelle bekomm ich ein Java Heap Out Of Space Exception... Hier mal de Code.

Das reader Funktion:


```
public static BufferedImage LoadImage(URL fileToLoad) {
		BufferedImage result = null;
		BufferedImage img = null;
		Graphics g;

		try {
			img = ImageIO.read(fileToLoad); 
            result = new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_3BYTE_BGR); 
            g = result.createGraphics(); 
            g.drawImage(img, 0, 0, null); 
            g.dispose();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
```

Und hier das speicher in einem 2-Dimensionalen Array von meiner Tile-Klasse:


```
public void fillMap() {
	
		Runnable runnable = new Runnable() {
			JProgressBar progressBar = new JProgressBar(0, mapTiles.length * mapTiles.length);
			JFrame f = new JFrame();
			int numberOfTiles = 0;
			public void run() {
				progressBar.setVisible(true);
				progressBar.setStringPainted(true);
				f.add(progressBar);
				
				f.setPreferredSize(new Dimension(100,20));
				f.setSize(new Dimension(100,20));
				f.setAlwaysOnTop(true);
				f.setVisible(true);
				
				
				for (int x = 0; x < mapTiles.length; ++x) {
					for (int y = 0; y < mapTiles.length; ++y) {
						URL mypic = getClass().getClassLoader().getSystemResource("data/pictures/Grass1.jpeg");
						mapTiles[x][y] = new Tile(x * 64, y * 64, ImageLoader.LoadImage(mypic));
						numberOfTiles++;
						javax.swing.SwingUtilities.invokeLater(new Runnable() {
							public void run() {
								progressBar.setValue(numberOfTiles);
							}
						});
					}
				}
			}
		};
		Thread thread = new Thread(runnable);
		thread.start();
	}
```

Ich glaube ein meiner LoadImage Funktion stimmt irgendetwas nicht...

Mfg, Templon


----------



## Ark (30. Mai 2007)

Templon hat gesagt.:
			
		

> ```
> public static BufferedImage LoadImage(URL fileToLoad) {
> BufferedImage result = null;
> BufferedImage img = null;
> ...


Du lädst ein Bild, um anschließend selbiges in ein neues Bild zu malen und das alte zu verwerfen? Wie witzlos ist denn das? oO

EDIT:


			
				Templon hat gesagt.:
			
		

> ```
> for (int x = 0; x < mapTiles.length; ++x) {
> for (int y = 0; y < mapTiles.length; ++y) {
> URL mypic = getClass().getClassLoader().getSystemResource("data/pictures/Grass1.jpeg");
> ```



Und bei diesem Code würde ich erst recht streiken!

Ark


----------



## Templon (30. Mai 2007)

Wenn ich das nicht mache habe ich nur noch etwa 10 FPS und sonst etwa 180...


----------



## Ark (30. Mai 2007)

Siehe EDIT oben. 

Vielleicht solltest du versuchen, die Bilder gleich im passenden Format abzuspeichern, dann müssen sie nicht erst umständlich umgewandelt werden. 

Ark


----------



## Templon (30. Mai 2007)

Vielleicht könntest du noch sagen was daran nicht gut ist? Deine Kommentare bringen mich kein bisschen weiter. Wie soll ich die gleich im richtigen Format abspeichern? Bekomm ja von der Funktion ImageIO.read einfach ein BufferedImage zurück?


----------



## Ark (31. Mai 2007)

Templon hat gesagt.:
			
		

> ```
> URL mypic = getClass().getClassLoader().getSystemResource("data/pictures/Grass1.jpeg");
> ```


getClass() wird hier auf this angewandt. this ist eine Konstante, folglich sind getClass() und getClassLoader() ebenfalls konstant. "data/pictures/Grass1.jpeg" ist eine String-Konstante, und da getClassLoader() und dieser String konstant sind, ist auch getSystemResource("data/pictures/Grass1.jpeg") konstant. Meine Frage: Wozu um alles in der Welt lädst du zig mal dasselbe Bild? Und jetzt zähle mal durch, wie häufig du in deiner geschachtelten Schleife new benutzt, und wie viele davon _wirklich nötig_ sind. Versuche, deinen Fortschrittsbalken anders zu aktualisieren. Generell gilt in Schleifen: Entferne Konstanten so weit wie nur irgendwie möglich.

Was die Bilder angeht: Versuche, deine Bilddateien derart anzupassen, dass ImageIO.read(…) sofort ein BufferedImage als TYPE_3BYTE_BGR oder in einem anderen schnellen Format liefert.

Ark


----------



## EgonOlsen (31. Mai 2007)

Das Umkopieren beim Laden sollte kein Problem sein. Aber (bei 50*50) 2500mal dasselbe Bild zu laden, das soll wohl langsam sein. Selbst wenn jeder Vorgang nur 4ms dauert, sind das 2500*4=10000ms=10sek. Lade die benötigten Bilder einmal, nicht 2500mal. Und du musst in deinem Array auch nicht 2500 Instanzen von einem Bild identischen Inhaltes halten. Lade einmal, und referenziere auf diese eine Instanz in deinem Array. Dann hört auch die Speicherfresserei auf.


----------



## Templon (31. Mai 2007)

Hmm danke stimmt ich werde das anders lösen müssen. Ich werde das irgendwie so lösen 


```
TileArray = {1,1,1,1,1,2,1,1,2 etc.}
```

und die zahlen stehen dann für die Bilder... Und die Bilder laden geht jetzt schneller, hab ein wenig im Internet geforscht und ein paar nützliche Funktionen gefunden.

Danke für die schnelle Hilfe!


----------

