在Java中没有内存问题的缩略图加载大图像?

时间:2011-05-03 19:27:50

标签: java memory-management image-processing thumbnails

我试图让用户从他们的硬盘加载图像,并在GUI中以视觉形式呈现这些缩略图列表(带有添加到JList的图标的JPanel)。我目前正在使用ImageIO.read()获取BufferedImage并为每个图像使用getScaledInstance(听说你不应该使用它)。

它适用于小图像,但加载超过四张照片(5000x3000或其他一些),我得到“java.lang.OutOfMemoryError:Java堆空间”。不保存对全尺寸BufferedImage的引用,所以我认为垃圾收集器会处理它并且只保留缩放的图像(不应该占用太多内存),但它看起来不像。我也踩了getRuntime()。gc()和System.gc(),没有效果。

从文件加载缩放图像的任何好方法,而不会遇到内存错误?显然很多软件都设法做到这一点,但也许不是用Java做的。外部库是可以的。


当前代码:

BufferedImage unscaledImage = ImageIO.read(imageFile);

int unscaledHeight = unscaledImage.getHeight();
int unscaledWidth = unscaledImage.getWidth();

int imageRatio = unscaledHeight/unscaledWidth;

if (imageRatio >= 1) {
    return new ImageIcon(unscaledImage.getScaledInstance(width,-1,Image.SCALE_FAST));
} else {
    return new ImageIcon(unscaledImage.getScaledInstance(-1,height,Image.SCALE_FAST));
}

2 个答案:

答案 0 :(得分:8)

问题在于BufferedImage本身的使用。当文件被读入内存时,你将没有堆空间。根据具体情况,您可以使用图像阅读器,也可以增加堆的大小。

我建议您使用图像阅读器。例如,要获得图像阅读器,您的代码将是这样的:

  // Create an image input stream on the image
    ImageInputStream iis = ImageIO.createImageInputStream(o);

    // Find all image readers that recognize the image format
    Iterator iter = ImageIO.getImageReaders(iis);
    if (!iter.hasNext()) {
        // No readers found
        return null;
    }

    // Use the first reader
    ImageReader reader = (ImageReader)iter.next();

来自:http://www.exampledepot.com/egs/javax.imageio/DiscType.html

您可以通过调用reader.getAspectRatio()

来获得ImageReader

我不确定你是如何从ImageReader转到缩略图的。

答案 1 :(得分:0)

JVM有一种缓存图像的恶习。解决问题的一种方法是:

  1. 创建指向图片的InputStream
  2. 将整个图像数据读入byte[](使用标准I / O API - imageio之外等。)
  3. ByteArrayInputStream
  4. 创建byte[]
  5. 使用ByteArrayInputStream作为ImageIO.read(InputStream)
  6. 的来源

    因为JVM不知道从哪个资源获取图像字节,所以它无法唯一地识别图像,也不会对其进行缓存。


    请注意,我找不到任何支持我所说的文件。这只是过去的经验。