Java: Reading images and displaying as an ImageIcon

I'm writing an application which reads and displays images as ImageIcons (within a JLabel), the application needs to be able to support jpegs and bitmaps.

For jpegs I find that passing the filename directly to the ImageIcon constructor works fine (even for displaying two large jpegs), however if I use ImageIO.read to get the image and then pass the image to the ImageIcon constructor, I get an OutOfMemoryError( Java Heap Space ) when the second image is read (using the same images as before).

For bitmaps, if I try to read by passing the filename to ImageIcon, nothing is displayed, however by reading the image with ImageIO.read and then using this image in the ImageIcon constructor works fine.

I understand from reading other forum posts that the reason that the two methods don't work the same for the different formats is down to java's compatability issues with bitmaps, however is there a way around my problem so that I can use the same method for both bitmaps and jpegs without an OutOfMemoryError?

(I would like to avoid having to increase the heap size if possible!)

The OutOfMemoryError is triggered by this line:

img = getFileContentsAsImage(file); 

and the method definition is:

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; 
}

The stack trace is:

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)
7
задан 11helen 30 March 2010 в 12:31
поделиться

3 ответа

У вас заканчивается память, потому что ImageIO.read () возвращает несжатое BufferedImage , который очень велик и сохраняется в куче, поскольку на него ссылается ImageIcon . Однако изображения, возвращаемые Toolkit.createImage , остаются в сжатом формате (с использованием частного класса ByteArrayImageSource .)

Вы не можете читать BMP с помощью Toolkit.createImage (и даже если бы вы могли, он все равно оставался бы несжатым в памяти, и у вас, вероятно, снова закончилось бы пространство кучи), но вы можете прочитать несжатое изображение и сохранить его в массиве байтов в сжатой форме, например

public static ImageIcon getPNGIconFromFile(File file) throws IOException {
    BufferedImage bitmap = ImageIO.read(file);
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    ImageIO.write(bitmap, "PNG", bytes);
    return new ImageIcon(bytes.toByteArray());
}

Таким образом, несжатый битовый массив должен храниться в памяти только тогда, когда он загружается или визуализируется.

3
ответ дан 7 December 2019 в 16:41
поделиться

Пробовали ли вы это?

ImageIcon im = new ImageIcon(Toolkit.getDefaultToolkit().createImage("filename"));
0
ответ дан 7 December 2019 в 16:41
поделиться

Неужели у вас действительно просто закончилась память? Я имею в виду, возникает ли ошибка, если вы запускаете java, скажем, с -Xmx1g ?

0
ответ дан 7 December 2019 в 16:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: