我试图让用户从其硬盘驱动器中加载图像,并在GUI中以缩略图列表的形式直观显示这些图像(JPanel的图标添加到JList)。我目前正在使用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)); }
问题出在使用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
拥有ImageReader的人可以通过调用以下命令获得宽高比 reader.getAspectRatio()
reader.getAspectRatio()
我不确定您如何将ImageReader转换为缩略图。