Image's vorladen?

Status
Nicht offen für weitere Antworten.

Titanpharao

Bekanntes Mitglied
Hi,

ich habe ein Programm, wo immer große Bilder in Hintergrund gelegt werden. Diese sind ~640x480 Pixel groß.

Jetzt besteht das Problem, das wenn ich die Panels mit den Bilder zum ersten mal aufrufe, es eine ganz kurze Zeit dauert, bis diese dagestellt werden. Beim zweiten mal Aufrufen sind diese soft da.

Also als ob sie "vorgeladen sind" Kann ich dieses Vorladen auch selber realisieren? Damit der Benutzer von Anfang an die Bilder sieht, ohne die Wartezeit?
 

L-ectron-X

Gesperrter Benutzer
Ja, benutze dazu die Klasse java.awt.MediaTracker.
Möglicherweise könnte es auch mit ImageIO eine Lösung geben.
 

Titanpharao

Bekanntes Mitglied
Sagt mir alles nichts :(

Code:
package imoy;


import java.awt.*; 
import java.io.BufferedReader;
import java.io.FileReader;

public class Textureloader{
	private Image texture[];
	
	public Image[] loadtexture(String pfad){
		try {
			BufferedReader ls = new BufferedReader(new FileReader(pfad));
			int anz=0;
			while ((ls.readLine()) != null)anz++;
			BufferedReader x = new BufferedReader(new FileReader(pfad));
			texture=new Image[anz];
			for(int i=0;i<anz;++i){
			pfad=x.readLine();
			texture[i]=Toolkit.getDefaultToolkit().getImage(pfad);
			}
			} catch (Exception e) {
				System.out.println("Fehler beim Laden der Texture-Datei!");
			}
		return texture;
	}
}

Im Moment sieht das so aus einfach ein IMAGE[]. Im Programm kann ich die dann über denn Index aufrufen.
(ja Vector wäre besser kannte ich aber damals noch nicht ;-) )
 

wayne

Bekanntes Mitglied
im prinzip musst du das laden des panels vom laden der bilder abkoppeln. das realisiert man sinnvollerweise über einen thread. die konstruktion müste so aussehen, daß du bei programmstart bzw. sobald dein hier gepostetes parameter pfad vorliegt, du einen extra thread mit dem laden der bilder beauftragst. wenn dann dein panel (deine view) geladen werden soll, checkt diese, ob das bild, welches sie anzeigen soll, bereits vollständig geladen wurde. wenn ja, zeigt sie dieses an, ansonsten wartet sie bis das bild da ist.

um das in deinem programm zu realisieren musst du deinen Texturloader von Thread erben lassen. am besten baust du dazu einen konstruktor, der als parameter den pfad übergeben bekommt, damit sichergestellt ist, daß immer ein pfad vorhanden ist. überschreibe dann die run() methode mit dem code, den du hier in der methode loadtexture(...) gepostet hast. dabei wäre es natürlich schöner, wenn das parameter pfad, welches ja dann eine globale variable ist, von der methode nicht ständig geändert wird. das könnte ein lokale variable besser erledigen und dein texturloader-thread kann jederzeit, wenn er einen neuen pfad zum laden erhält, überprüfen, ob das überhaupt notwendig ist, weil ggf. von diesem pfad bereits geladen wurde. zu alle dem lege in dem texturloader-thread paralel zum array texture noch ein globales array isLoaded[] an. beide array's werden beim laden von bildern auf gleiche länge getrimmt, nämlich auf die anzahl der bilder. wenn deine run-methode ein bild geladen hat, setzt du den entsprechenden index in isLoaded[] auf true. erzeuge zusätzlich eine synchronized methode in der art getImage(int index). in diese methode implementierst du zunächst eine überprüfung, ob überhaupt dieser index jemals existieren kann (weil ggf. gar nicht soviele bilder vorhanden sind ... kleiner schutz vor programmierfehlern), dann eine überprüfung von isLoaded. wenn isLoaded = false, springst du in eine warteschleife, in dieser art:
Code:
...
while( !isLoaded[index] )
   try {
      sleep(100); // angabe in millisekunden. alternativ kannst du auch wait(...) aufrufen.
   }
   catch( Exception e ){
       e.printStacktrace();
   }
abschließend gibst du dann das entsprechende bild zurück.

ausserdem hier noch ein wichtiger hinweis für dich. du kannst ernsthafte probleme bekommen, wenn du die bilder so lädst, ohne zu überprüfen, ob das bild auch wirklich fertig geladen wurde. wenn du mal mit System.currentTimeMillis() dir ansiehst, wie lange der aufruf Toolkit.getDefaultToolkit().getImage(pfad) benötigt, wirst du feststellen, daß hier überhaupt keine zeit vergeht. das liegt daran, daß dieser aufruf das bild asynchron läd. deshalb hatte L-ectron-X wohl auch auf den MediaTracker verwiesen. dieser bietet dir die ideale möglichkeit ein bild aufs vollständige laden zu prüfen. durch den MediaTracker kannst du dir sogar das array isLoaded[] sparen. lege einfach global ein MediaTracker-objekt an und füge deine bilder nach dem laden mit dem Toolkit diesem hinzu (mit fortlaufendem index, also dem gleichen index, den du in deinem ganzen programm für die bilder verwenden willst. mittels der methode checkID(int) des MediaTrackers kannst du das gleiche tun, was ich oben mit isLoaded[index] gemacht habe, oder du verwendest gleich, anstatt dieses ganzen blocks den aufruf waitForID(int).

beachte übrigends ausserdem, daß dir nicht unendlich viel speicher zur verfügung steht, du also ggf. mal bilder wieder aus dem speicher rauswerfen wirst müssen, falls zuviele zu laden sind. ohnehin würde ich anstatt eines arrays eher einen Vector oder eine ArrayList zum halten der bilder verwenden.

viel erfolg

wayne
 

Titanpharao

Bekanntes Mitglied
Hm...also liegt es daran, dass das Image nicht wirklich geladen wurde, sondern nur der Pfad bereit gestellt wurde. Weil wie gesagt, wenns einmal aufgerufen wurde, dann gehts.

Die Bilder sind meist nur 100kb groß. Auch wenns am Ende weit über 500 sind, so werde ich nicht mal die 50MB grenze überschreiten...denke das normal ;-)

Im moment siehts so aus mit dem erstellen, der panels + Bilder. Hatte früher mal es über paint() realisiert, wovon ich mich aber verabschiedet habe, weils zu umständlich war...jetzt sinds einfach nur Labels.

Code:
   public JPanel nummer1(){ 
      j= new JPanel(); 
      j.setLayout(null); 
      j.setSize(640, 480); 
      l=new JLabel(new ImageIcon("resc/fg.gif")); 
      l.setSize(32, 32); 
      l.setLocation(x, y); 
      JLabel s=new JLabel(new ImageIcon("resc/bg.gif")); 
      s.setSize(640, 480); 
      s.setLocation(0, 0); 
      JButton b1=new JButton(new ImageIcon("resc/button.gif")); 
      b1.setSize(100, 25); 
      b1.setLocation(0, 455);
      b1.addActionListener(new ActionListener() { 
         public void actionPerformed(ActionEvent evt) { 
               chancepanels(0); 
               run=false; 
            } 
      }); 
      j.add(b1); 
      j.add(l); 
      j.add(s); 
      
      return j; 
   }
 

Titanpharao

Bekanntes Mitglied
Ah glaube ich habs...es ruft denn Textureloader immer nach jedem Panel wechsel auf...das natürlich gleich zwei mal doof. Ich bau das eh nochmal alles um. Das muss noch besser gehen, viel besser.
 
G

Guest

Gast
jo, bastel noch etwas daran. hab auch schon vielfach die erfahrung machen müssen, daß es in java zig wege gibt um mit bildern umzugehen, aber einen performaten sinnvollen weg zu erarbeiten, dauert seine zeit.

lass mich dich aber an dieser stelle noch schnell korrigieren, bezüglich der größe deiner bilder im speicher: wie du schreibst, sind deine bilder alle um die 640x480 pixel groß. nach dem laden liegen sie dir als Image vor. dabei kannst du davon ausgehen, daß jedes pixel in einem int abgespeichert wird, womit dann für R-, G- und B-kanal jeweils 8-bit zur verfügung stehen und ggf. noch 8-bit platz für einen alpha-kanal wäre. somit hat jedes pixel also 2 byte. 640 * 480 * 2 = 614400 byte, also ca. 600 KB. das heißt also, daß dein speicher mit ca. 100 bildern voll ist, sofern du ihn nicht mittels java-start-parameter -Xmx erweiterst.

du kannst die größe der bilder natürlich verringern. da das aber rechenaufwand bedeutet, empfehle ich dir, dies ebenfalls in einem seperaten thread im hintergrund zu erledigen. verringern kannst du die größe beispielsweise, indem du das farbmodel der bilder änderst. hierfür bietet sich ein PackedColorModel oder noch besser ein IndexColorModel an. zum PackedColorModel kann ich nicht viel sagen, für ein IndexColorModel zählst du zunächst die unterschiedlichen farben ab und legst diese in eine liste. anschließend ersetzt du die pixelwerte durch die indizes der farben. dadurch werden die bilder in der regel wesentlich kleiner, abhängig von der anzahl der verschiedenen farben. hätte ich das zu programmieren, würde ich zunächst meine view anfragen lassen, ob das verlangte bild komprimiert vorliegt. ist das nicht der fall, sollte sie das unkompimierte bild anzeigen, bis das komprimierte bild vorhanden ist (benachrichtigung per listener auf den farbmodel-ändernden-thread). zu dem ganzen würde ich mir ein ImageModel basteln, welches die geladenen bilder sowie die farbmodel-geänderten halten kann und welches diese von den beiden threads (dem bilder-ladenden und dem farbmodel-änderndem) erhält. wenn das model ein farbmodel-geändertes bild erhält, ersetzt es das ursprünglich geladene, um speicher einzusparen. am besten ruft es bei der gelegenheit gleich System.gc() auf, damit dann der speicher auch möglichst zeitnah freigegeben wird.

viel erfolg

wayne
 

Titanpharao

Bekanntes Mitglied
Aber wieso denn das?

Im Windows sind die auch nur 100kb groß. Werden die nicht einfach immer über denn pfad geladen?

Kann ja mal aus spaß 100x das selbe Bild reinlegen und schauen obs mir explodiert :lol:

Also der Textureloader kann auch gern 150 640x480 Bilder laden ;-) das dem egal...
nur wenn ich die verschiedenen panels aufrufe merke ich gerade steigt der speicher langsam an..fält zwar auch wieder am wenn ganz schnell machst geht das schnell von 23MB auf 31 hoch
 

wayne

Bekanntes Mitglied
klar haben die unter windows, wie auch unter anderen betriebssystemen nur 100KB, komprimiert. aber wenn du die in java einlädst, werden sie entpackt. es sei denn, du hast sie als BMP-dateien herumliegen, die sind häufig vollständig unkomprimiert. aber sonst ... GIF ist häufig schon durch sein indiziertes farbmodel komprimiert, JPEG sowieso durch diskrete cosinus-transformationen ... ... ...

ansich, wenn du den MediaTracker verwendest, damit dein programm wartet, bis das jeweilige bild vollständig geladen wurde, sollte nach dem laden jedes bildes der speicherbedarf deines programms sich entsprechend erhöhen. ich persönlich verwende meißtens com.sun.image.codec.jpeg.JPEGImageDecoder zum laden von JPEGs, da dieser das bild gleich als BufferedImage zurückgibt, die methode ohnehin erst dann wiederkehrt, wenn das bild vollständig geladen wurde und ich bilder auch über zeichenketten laden kann, wenn sie beispielsweise einer datenbank entspringen. bei dem ist das so ... logischerweise. denn jedes bild befindet sich nach dem laden vollständig im speicher. und genau das ist es ja auch, was ich haben will, sonst benötigt mein programm zeit bis das bild aufgebaut ist. bist du sicher, daß deine bilder vollständig geladen wurden? sprich, hast du den MediaTracker benutzt um das abzuklären?

aber eh egal. ob du das mit der kompression im speicher machst oder nicht bleibt dir überlassen. hängt von den fakten ab, ob die anzahl der bilder jemals einen kritischen wert erreichen wird und ob du beim benutzer nicht noch beispielsweise die startoption -Xmx255m zum startbefehl hinzufügst. wenn dir 64MB (standardwert des speichers für java-anwendungen) für mehr als 150 bilder ausreichen und du niemals mehr als 500 bilder gleichzeitig im speicher haben wirst sollten es 255MB tun.

viel erfolg

wayne
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
XWing Swing Image anzeigen und probleme mit klassen AWT, Swing, JavaFX & SWT 3
Telisti Javafx Image wird nicht richtig integiert AWT, Swing, JavaFX & SWT 8
K JavaFX Bildergalerie aus Image Ordner laden AWT, Swing, JavaFX & SWT 3
JMölleri Swing Image wird unscharf dargestellt AWT, Swing, JavaFX & SWT 2
L AWT .gif image transparent machen AWT, Swing, JavaFX & SWT 3
kodela angezeigtes Image entfernen AWT, Swing, JavaFX & SWT 1
R Java, GUI, Hintergrundbild, Image, AWT, Swing, JavaFX & SWT 4
R Swing Background Image in JFrame implementieren AWT, Swing, JavaFX & SWT 40
T Swing Buffered Image anzeigen AWT, Swing, JavaFX & SWT 45
L Image kann nicht gefunden werden AWT, Swing, JavaFX & SWT 1
S Stretch Image in ImageView AWT, Swing, JavaFX & SWT 4
N Swing Image aus Web laden und in Icon umwandeln AWT, Swing, JavaFX & SWT 4
Fiedlerdan Image-Pfad Probleme nach Export aus Eclipse AWT, Swing, JavaFX & SWT 31
L JavaFX Image mit Blureffect AWT, Swing, JavaFX & SWT 2
Bluedaishi JavaFX Button Image aus Datenbank AWT, Swing, JavaFX & SWT 13
F javaxt.io.Image getBufferedImage liefert null AWT, Swing, JavaFX & SWT 1
Yjuq JavaFX Custom Control - Image resize AWT, Swing, JavaFX & SWT 0
D Java FX Image in einer Webanwendung annotieren und den Bereich ausschneiden AWT, Swing, JavaFX & SWT 0
I Bild über FXML (ImageView, Image) anzeigen AWT, Swing, JavaFX & SWT 1
T Image Loader lädt Bild nicht AWT, Swing, JavaFX & SWT 10
J 2D-Grafik Background Image Klasse AWT, Swing, JavaFX & SWT 14
Q AWT TicTacToe Image auf Button hinzufügen AWT, Swing, JavaFX & SWT 5
BreakdownBob Swing JLabel verschwindet hinter Image AWT, Swing, JavaFX & SWT 2
L JavaFX leeres weißes Image - javafx.scene.image.Image AWT, Swing, JavaFX & SWT 2
L JavaFX Image im ImageView auf Scroll Listener reagieren AWT, Swing, JavaFX & SWT 5
Naxon89 JavaFX Image wird nicht korrekt geladen AWT, Swing, JavaFX & SWT 3
W Javafx - Image soll sich mit der Camera mitbewegen AWT, Swing, JavaFX & SWT 1
B Graphics to Image AWT, Swing, JavaFX & SWT 3
L Image in anderes kopieren AWT, Swing, JavaFX & SWT 0
T Swing Image wird nicht geladen AWT, Swing, JavaFX & SWT 1
S JavaFX Image Skalierung in Scrollpane, Scrollpane resized sich nicht AWT, Swing, JavaFX & SWT 5
I Image im PopupMenu vom SystemTray AWT, Swing, JavaFX & SWT 8
F JavaFX Position von Image angeben/verändern AWT, Swing, JavaFX & SWT 2
M JavaFX Image View Würfel berechnen AWT, Swing, JavaFX & SWT 3
L JButton mit Image AWT, Swing, JavaFX & SWT 5
F Swing Image einem Button hinzufügen AWT, Swing, JavaFX & SWT 5
B Resize von Image nach Resize von Button AWT, Swing, JavaFX & SWT 1
T Image aus "nicht-src-ordner" AWT, Swing, JavaFX & SWT 5
vodkaz (javafx) Image Problem AWT, Swing, JavaFX & SWT 2
C Image laden und Speichern - Image wird auf JPanel nicht angezeigt AWT, Swing, JavaFX & SWT 4
M Image in JTable einfügen AWT, Swing, JavaFX & SWT 9
M Image aus MS Access anzeigen lassen AWT, Swing, JavaFX & SWT 9
H Image im Array per Knopfdruck ändern AWT, Swing, JavaFX & SWT 6
H Swing JList/JTable mit JButton, JTextField, Image, JComboBox und JLable AWT, Swing, JavaFX & SWT 2
P Image oder Icon auf Tooltip zeichnen AWT, Swing, JavaFX & SWT 4
G JavaFX Image vergrößern AWT, Swing, JavaFX & SWT 5
U Image mit Zeichenbereich rotieren AWT, Swing, JavaFX & SWT 3
P Speicherproblem SWT.Image in Nebula-Gallery AWT, Swing, JavaFX & SWT 3
L JavaFX: Bild in Image einlesen AWT, Swing, JavaFX & SWT 11
D Image soll langsam sichtbar werden AWT, Swing, JavaFX & SWT 4
D JLabel Image ausrichten AWT, Swing, JavaFX & SWT 2
Z Flackern trotz Offscreen Image / Doublebuffer, (+ Frage zu Pixelvergleich) AWT, Swing, JavaFX & SWT 25
bluerob Problem beim Image zeichnen via andere Klasse AWT, Swing, JavaFX & SWT 7
H Image Icon ersetzen AWT, Swing, JavaFX & SWT 8
I Image Button AWT, Swing, JavaFX & SWT 4
U IntBuffer zum Image konvertieren. AWT, Swing, JavaFX & SWT 9
S Eigene JComponent Image zeichnen AWT, Swing, JavaFX & SWT 3
T 2D-Grafik Slideshow (DoubleBuffering und Image transformieren/bewegen) AWT, Swing, JavaFX & SWT 6
K Swing Warum bleibt das Image immer gleich AWT, Swing, JavaFX & SWT 4
L Swing dynamisches Image-Panel in Layout einbinden AWT, Swing, JavaFX & SWT 10
R Image laden sehr langsam AWT, Swing, JavaFX & SWT 7
D Image.getScaledInstance() vs. Netzwerkverbindung??? AWT, Swing, JavaFX & SWT 2
reibi SWT Image viewer AWT, Swing, JavaFX & SWT 2
lumo SWT Image funktion auf ImageDaten AWT, Swing, JavaFX & SWT 9
A Applet .gif in applet Image nicht animiert angezeigt AWT, Swing, JavaFX & SWT 4
M Image wird nicht neugezeichnet nach dem Wechsel AWT, Swing, JavaFX & SWT 2
lumo SWT Image Pattern AWT, Swing, JavaFX & SWT 5
P Image mehrfach in ein BufferedImage zeichnen AWT, Swing, JavaFX & SWT 7
M Swing Image in JPanel als Componente AWT, Swing, JavaFX & SWT 2
P nicht sichtbares JPanel / JFrame als Image speichern AWT, Swing, JavaFX & SWT 3
T Image skaliert in Variable speichern AWT, Swing, JavaFX & SWT 6
S Image wird nicht (immer) in paintComponent gezeichnet? AWT, Swing, JavaFX & SWT 6
S Swing Image wird nicht geladen AWT, Swing, JavaFX & SWT 2
0 Mousecurser mit Image hinterlegen AWT, Swing, JavaFX & SWT 4
B Swing Drag&Drop mit Feedback (Image am Mauszeiger) AWT, Swing, JavaFX & SWT 7
N Java Choice Bilderausgabe - images - - image - AWT, Swing, JavaFX & SWT 2
D iText PdfPCell mit Image AWT, Swing, JavaFX & SWT 3
S 2D-Grafik Icon in Image (System Icons) AWT, Swing, JavaFX & SWT 2
S Button mit Image AWT, Swing, JavaFX & SWT 7
A Skaliertes Image pixelweise bearbeiten AWT, Swing, JavaFX & SWT 6
L Swing Image zur Laufzeit verändern AWT, Swing, JavaFX & SWT 6
F SWT GC drawText auf halbtransparentem Image AWT, Swing, JavaFX & SWT 21
G Swing JEdtitorPane und HTML Image Seite AWT, Swing, JavaFX & SWT 2
C Image mit Graphics2D zeichnen AWT, Swing, JavaFX & SWT 9
C Image performant skalieren AWT, Swing, JavaFX & SWT 5
D SWT Image Farbtiefe AWT, Swing, JavaFX & SWT 2
L Swing Auf unabhängiges Image-Objekt zeichnen AWT, Swing, JavaFX & SWT 8
lumo SWT Composite + Image + zeichnen AWT, Swing, JavaFX & SWT 4
V Ein Image als Button (nicht mit JButton(Icon)) AWT, Swing, JavaFX & SWT 5
D Image Viewer gesucht AWT, Swing, JavaFX & SWT 5
Kr0e Image schärfen AWT, Swing, JavaFX & SWT 2
R Bild drehen UND skalieren (Image bzw BufferedImage) AWT, Swing, JavaFX & SWT 5
T Image auf Image zeichnen AWT, Swing, JavaFX & SWT 2
E Warum ist offscreen (mit Image) schneller? AWT, Swing, JavaFX & SWT 11
G Swing Image speichern / 0 Byte AWT, Swing, JavaFX & SWT 7
H Image abspeichern AWT, Swing, JavaFX & SWT 4
B Swing Image als Hintergrund im JInternalFrame - Problem AWT, Swing, JavaFX & SWT 3
W Image in jar einbauen AWT, Swing, JavaFX & SWT 20
Luk10 AWT Image und die Skalierung! AWT, Swing, JavaFX & SWT 3
L JPanel als Image speichern AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben