ImageIcon in Byte-Array ablegen

gbunge

Aktives Mitglied
Hallo Java
ich habe mir ein Programm programmiert, mit dem ich einen Ordner mit
unsortierten Bilder so aufbereiten kann, dass die Bilder für eine
Diashow thematisch und zeitlich geordnet sind.
Dazu lese ich alle Bilder ein und skaliere sie zu ImageIcons.

Das Programm läuft so wie ich es mir gedacht habe, allerdings nur
so lange wie ich ( für die Programmierphase ) nur zehn Bilder einlese.
Beim ersten Lauf mit einem tatsächlichen Bildordner stieg es mit einer
Exception aus.
" Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space "
Das tritt ein, wenn ich mehr als 120 Bilder einlesen will.

Ich habe mir nun eine Änderung überlegt.
Ich lege alle ImageIcons an, speichere sie aber nicht im Programm,
sondern in jeweils einem Binär-File auf der Festplatte.

Hier ist nun mein Problem.
Mir gelingt es nicht, das ImageIcon in ein Byte-Array zu schreiben.

[CODE lang="java" title="Programmsegment"]

private static ImageIcon[] iconList;

// Image in ImageIcon wandeln
iconList[0] = new ImageIcon( sImg );

// ImageIconList speichern
BufferedOutputStream bos = null;
try {

bos = new BufferedOutputStream( new FileOutputStream("datei.bin") );
byte[] buf = (byte)iconList[0];
bos.write( buf );
}
catch( IOException ex) {
System.out.println(ex);
}
finally {
if(bos!=null)
try {
bos.close();
}
catch(Exception ex) {
}
}

[/CODE]

Kann mir dabei jemand helfen?
Gruss GBunge
 
Ich verstehe gerade den großen Unterschied bzgl. des Speicherbedarfs nicht: wenn Du eine Reihe von Bildern nacheinander einliest, skalierst und nur die skalierte Version im Speicher hältst, ist das größte Bild im Wesentlichen der Overhead gegenüber dem Einlesen von bereits skalierten Bildern.

Auf welche Größe skalierst Du denn?

(NB: für das, was Du gerade vorhast, brauchst Du ImageIcon nicht. Du kannst mit ImageIO arbeiten).
 
Ich verstehe gerade den großen Unterschied bzgl. des Speicherbedarfs nicht: wenn Du eine Reihe von Bildern nacheinander einliest, skalierst und nur die skalierte Version im Speicher hältst, ist das größte Bild im Wesentlichen der Overhead gegenüber dem Einlesen von bereits skalierten Bildern.

Auf welche Größe skalierst Du denn?

(NB: für das, was Du gerade vorhast, brauchst Du ImageIcon nicht. Du kannst mit ImageIO arbeiten).
Hallo mihe7,
1. mit "Bilder einlesen" meine ich, dass ich den absoluten Pfad in eine ArrayList eintrage und bei Anzeige des Bildes
vorher die Datei einlese und das Bild skaliere. Das Bild steht also vorher nicht im Programm. Aber das ImageIcon
speichere ich natürlich im Programm, damit ich nicht jedesmal skalieren muss.

2. skaliert wird das Bild nach dem Einlesen der Datei auf die Größe des Programmfensters. Das ImageIcon ist also
kleiner als das Originalbild und nur das ist im Programm gespeichert und führt nach etwa 100 Bildern zur Extention:

3. zum dritten Punkt: ImageIcon benutze ich, weil das Bildfenster im Programm ein JLabel ist.
und durch die Speicherung des ImageIcons in einer Binärdatei spare ich beim nächsten Anzeigen des Bildes die
langwierige Skalierung.
 
OK, dann würde ich folgendes machen:

1. nur ein ImageIcon
2. wenn ein Bild angezeigt werden soll, prüfen, ob das Bild bereits skaliert vorliegt
3. wenn ja, das skalierte Bild einlesen und anzeigen. Fertig.
4. wenn nein, das Bild skalieren, speichern und anzeigen. Fertig.

Auf diese Weise hältst Du immer nur ein Bild im Speicher. Zum Lesen/Schreiben kannst Du ImageIO verwenden. Das BufferedImage kannst Du in ein ImageIcon stecken.
 
OK, dann würde ich folgendes machen:

1. nur ein ImageIcon
2. wenn ein Bild angezeigt werden soll, prüfen, ob das Bild bereits skaliert vorliegt
3. wenn ja, das skalierte Bild einlesen und anzeigen. Fertig.
4. wenn nein, das Bild skalieren, speichern und anzeigen. Fertig.

Auf diese Weise hältst Du immer nur ein Bild im Speicher. Zum Lesen/Schreiben kannst Du ImageIO verwenden. Das BufferedImage kannst Du in ein ImageIcon stecken.
Ja, dabei muss ich aber das Bild vorher skalieren, damit es skaliert auf der Festplatte liegt ( Dein Punkt 3 )
auf der Festplatte liegt dann das originale Bild und sinnvollerweise in einem anderen Ordner das skalierte Bild.
So hatte ich es ja auch vor. Nur wollte ich statt des skalierten Bildes die Pixel in einer Binärdatei ablegen.
Ich dachte die ist weniger groß als eine JPG-Datei.
 
Oje, unkomprimiert ist das Billd Breite * Höhe * 3 Bytes groß 🙂
Hallo mihe7

ich habe die skalierten Bilder als verkleinerte JPG-Dateien in einem vorübergehenden Sonderordner mit dem originalen Namen gespeichert. Die Bilder im Sonderordner, angesehen mit einem Bildbetrachter , waren alle in Ordnung nur eben, entsprechend der Skalierung, kleiner.

Wenn ein bestimmtes Bild dargestellt werden sollte, dann habe ich es aus dem Sonderordner gelesen und statt des originalen Bildes das skalierte Bild angezeigt.
Das Bild wurde ohne Fehler eingelesen, aber leider war im Programm das Bild nicht zu sehen.
Das skalierte Bild habe ich mit der gleichen Methode eingelesen wie das originale Bild.

Ich habe mir dann ein anderes Verfahren ausgedacht!

Skaliert und im Programm behalten werden nur 100 Bilder ( etwa 30 Bilder unter der Exception Grenze ). Im Programm gibt es also immer nur 100 ImageIcons. Für die Bilder über 100 setze ich deren ImagIcon auf null bevor ich ein neue Bild einlese und skaliere. Da das Programm Bilder löscht, oder umbenennt, werden immer wieder Bilder total aus dem Programm heraus genommen und ich kann das entfernte ImageIcon durch ein neues ImageIcon ersetzen.

Die Idee fand ich super! Aber leider führte sie nicht zum Erfolg!

Bei der gleichen Grenze wie vorher trat die Exception auf, obwohl die Anzahl der, im Programm gehaltenen, ImageIcons konstant bei 100 lag.

Ich habe mal die Verwaltung der ImageIcons protokolliert. Die letzten 5 Ausgaben vor der Exception kopiere ich mal.

[CODE lang="java" title="Protokoll"]
125: vor Icon löschen: javax.swing.ImageIcon@19e64782 nach Icon löschen: null
126: vor Icon löschen: javax.swing.ImageIcon@13725820 nach Icon löschen: null
127: vor Icon löschen: javax.swing.ImageIcon@11070d8c nach Icon löschen: null
128: vor Icon löschen: javax.swing.ImageIcon@401fd345 nach Icon löschen: null
129: vor Icon löschen: javax.swing.ImageIcon@24283bbe nach Icon löschen: null
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
[/CODE]

Vieleicht hilft eine programmierte Garbage Collection??

Fällt Dir was ein?
 

Zurück
Oben