2010-03-30 11 views
6

Ich schreibe eine Anwendung, die Bilder als ImageIcons liest und anzeigt (in einem JLabel), die Anwendung muss JPEGs und Bitmaps unterstützen können.Java: Bilder lesen und als ImageIcon anzeigen

Für JPEGs finde ich, dass die Übergabe des Dateinamens direkt an den ImageIcon-Konstruktor funktioniert (auch für die Anzeige von zwei großen JPEGs), aber wenn ich ImageIO.read verwenden, um das Bild zu erhalten und das Bild an den ImageIcon-Konstruktor I übergeben Erhalte einen OutOfMemoryError (Java Heap Space), wenn das zweite Bild gelesen wird (unter Verwendung der gleichen Bilder wie zuvor). Wenn ich Bitmaps versuche, zu lesen, indem ich den Dateinamen an ImageIcon übergebe, wird nichts angezeigt, jedoch funktioniert das Lesen des Bildes mit ImageIO.read und anschließendes Verwenden dieses Bildes im ImageIcon-Konstruktor einwandfrei.

Ich verstehe aus dem Lesen anderer Forum Beiträge, dass der Grund, dass die beiden Methoden nicht die gleichen für die verschiedenen Formate arbeiten, ist Java Kompatibilitätsprobleme mit Bitmaps, aber es gibt einen Weg um mein Problem, so dass ich verwenden kann die gleiche Methode für Bitmaps und JPEGs ohne OutOfMemoryError?

(Ich mag die Heap-Größe, wenn möglich zu erhöhen, um zu vermeiden!)

Die OutOfMemoryError durch diese Linie ausgelöst werden:

img = getFileContentsAsImage(file); 

und die Methodendefinition ist:

public static BufferedImage getFileContentsAsImage(File file) throws FileNotFoundException { 
    BufferedImage img = null; 
    try { 
    ImageIO.setUseCache(false); 
    img = ImageIO.read(file); 
    img.flush(); 
    } catch (IOException ex) { 
    //log error 
    } 
return img; 
} 

Der Stack-Trace ist:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space 
     at java.awt.image.DataBufferByte.<init>(DataBufferByte.java:58) 
     at java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:397) 
     at java.awt.image.Raster.createWritableRaster(Raster.java:938) 
     at javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1056) 
     at javax.imageio.ImageReader.getDestination(ImageReader.java:2879) 
     at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:925) 
     at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:897) 
     at javax.imageio.ImageIO.read(ImageIO.java:1422) 
     at javax.imageio.ImageIO.read(ImageIO.java:1282) 
     at framework.FileUtils.getFileContentsAsImage(FileUtils.java:33) 
+0

Bitte geben Sie einen Beispielcode ein, der den OutOfMemoryError auslöst. – Thomas

Antwort

3

Sie haben nicht genügend Arbeitsspeicher, da ImageIO.read() ein unkomprimiertes BufferedImage zurückgibt, das sehr groß ist und im Heap beibehalten wird, da es von der ImageIcon referenziert wird. Doch die von Toolkit.createImage zurück Bilder bleiben in ihrem komprimierten Format (die private ByteArrayImageSource-Klasse.)

Sie können keine BMP lesen Toolkit.createImage mit (und selbst wenn Sie könnten es wäre immer noch unkomprimiert bleiben im Speicher und Sie würden wahrscheinlich heraus laufen von Heap-Speicherplatz wieder), aber was Sie tun können, ist das unkomprimierte Bild lesen und speichern Sie es in einem Byte-Array in komprimierter Form, z

Auf diese Weise muss die unkomprimierte Bitmap nur im Speicher gehalten werden, wenn sie geladen oder gerendert wird.

+0

Brilliant! Das funktioniert perfekt. Nur aus Interesse, warum funktioniert diese Methode nur mit "PNG" als FormatName bei der Verwendung einer Bitmap-Datei? – 11helen

+0

Es muss ein Format sein, das vom Toolkit lesbar ist und für das ein ImageIO-Plugin benötigt wird. GIF wird wahrscheinlich funktionieren (aber ist auf 8bpp beschränkt, so dass die Qualität reduziert werden kann.) JPEG wird auch funktionieren (aber funktioniert am besten für fotografische Bilder, die wahrscheinlich bereits im JPEG-Format waren, so dass es überflüssig wäre.) – finnw

0

Haben Sie das versucht?

ImageIcon im = new ImageIcon(Toolkit.getDefaultToolkit().createImage("filename")); 
+0

Es scheint nicht mit den Bitmaps zu arbeiten und schlägt auch mit den 2 großen jpegs: Ausnahme im Thread "Image Fetcher 0" java.lang.OutOfMemoryError: Java-Heap-Raum bei java.awt.image.DataBufferInt. (DataBufferInt.java:41) bei java.awt.image.Raster.createPackedRaster (Raster.java:458) bei java.awt.image.DirectColorModel.createCompatibleWritableRaster (DirectColorModel.java:1015) bei sun.awt. image.ImageRepräsentation.createBufferedImage (ImageRepresentation.java:230) bei sun.awt.image.ImageRepresentation.setPixels (ImageRepresentation.java:470) ... – 11helen

0

Es könnte nicht sein, dass Sie tatsächlich nicht mehr genügend Speicher haben? Ich meine, tritt der Fehler immer noch auf, wenn Sie Java mit, sagen wir, -Xmx1g ausführen?