我有一个简单的javafx应用程序,它可以批量操作图像(只是调整大小:))这是一个简单的javafx表单,带有源目录textField、目标目录textField和所需的尺寸。启动此应用程序后,没有任何操作的简单形式会消耗大约 65MB 内存...开始批处理后,内存消耗跳至 250 MB,然后不断增加。在处理 700 张图像后,我的应用程序消耗了大约 1,35GB 内存(图片大小约为 3500x2600 像素,大小已调整为 1920x1080)。如果我在每个图像后调用 gc()
,则内存约为 300 - 350 MB。但是您是否对 javafx 应用程序的较小内存要求有一些提示,或者 350 MB 就可以了,因为 Java 是虚拟机。感谢您的提示。大约几年前,我用 C# 编写了类似的应用程序,它消耗了大约 60 MB 的内存:) 它有很大的不同 :( 但我喜欢 Java 和多平台应用程序。当然,我通过 在第二个线程中打开图像ImageIO.read()
,然后转换为 BufferedImage()
,然后我用较小的尺寸创建新的 BufferedImage()
并绘制原始的 BufferedImage()
通过 Graphics2D()
生成新的较小图像
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g.dispose();
最后
ImageIO.write(backgroundThread.resize(1920, 1080), "jpg", new File(destinationPath + f.getFileName()));
感谢帮助
最佳答案
使用JavaFX Image constructor创建图像并调整其大小,而不是使用 BufferedImage和 ImageIO 。
内存消耗应改善为:
- 发生的格式转换较少,因此不需要存储中间格式。
当使用 JavaFX Image 构造函数时,JavaFX javadoc 指定:
Images can be resized as they are loaded (for example to reduce the amount of memory consumed by the image)
其他问题的答案
how I can save it on disk?
使用 JavaFX 将图像保存到磁盘目前(从最初的 Java 8 版本开始)是一个开放的、 Unresolved 功能请求:RT-18886 Implement Image writers for JavaFX 。
在实现 RT-18886 之前,您需要将图像转换为 BufferedImage在保存之前,为了使用 ImageIO用于将图像保存为 jpg
等格式。您可以使用SwingFXUtils去做这个。当您第一次将图像加载到内存中时,预先调整图像大小仍然是有效的,这就是 JavaFX Image 构造函数的工作原理。
I must also create a new Buffered Image and then draw it inside with Graphics2D.
您可以将图像加载为 JavaFX 图像,然后将其绘制在 JavaFX Canvas 上,使用 JavaFX GraphicsContext ,然后 snapshot the canvas获取一个新图像,您可以将其转换为 BufferedImage 并使用 ImageIO 保存。好吧,也许这不是最有效的流程,但它确实允许您(主要)坚持使用单个框架和 API,并避免一些潜在的线程问题。
I using SwingFXUtils.fromFXImage(im, null) but I have a strange filter on the pictures then
我不知道“奇怪的过滤器”到底是什么意思,但也许您正在看到RT-14647 Incorrect display of JPEG images ,该问题已在过去的 JavaFX 更新中修复。尝试针对最新的 Java 8 development release 运行看看您是否仍然遇到同样的问题。如果没有,您可以使用 mcve 创建一个新问题.
<小时/>替代方案
几乎可以肯定,有一种等效的方法可以仅使用 BufferedImage、ImageIO 和 awt/swing 框架来有效地保存调整大小的图像,但我对该 API 不够熟悉,无法评论如何完成此操作,而且我不是粉丝混合 Swing、AWT 和 JavaFX,除非您确实需要。
关于javafx调整图像大小的内存消耗提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25401185/