渲染大图像时出现javafx NullPointerException

Posted

技术标签:

【中文标题】渲染大图像时出现javafx NullPointerException【英文标题】:javafx NullPointerException when rendering big image 【发布时间】:2014-06-21 11:29:33 【问题描述】:

我正在尝试使用 JavaFX 8 下的 GraphicsContext.drawImage(...) 方法渲染 .png 图像。我的代码对于大小为 ~1000px x 2000px 的图像非常有效。 但不幸的是,我需要渲染大小为 7000px x 14000px 的图像。加载此图像也可以正常工作,但是在调用 drawImage(image, 0, 0, canvas.getWidth(), canvas.getHeight()) 方法时,我得到以下错误输出:

java.lang.NullPointerException
at com.sun.prism.impl.BaseGraphics.drawTexture(BaseGraphics.java:389)
at com.sun.prism.impl.ps.BaseShaderGraphics.drawTexture(BaseShaderGraphics.java:139)
at com.sun.javafx.sg.prism.NGCanvas.handleRenderOp(NGCanvas.java:1228)
at com.sun.javafx.sg.prism.NGCanvas.renderStream(NGCanvas.java:997)
at com.sun.javafx.sg.prism.NGCanvas.renderContent(NGCanvas.java:578)
... more rendering stuff here
at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2043)
at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1951)
at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:469)
at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:317)
at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:89)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:129)
at java.lang.Thread.run(Thread.java:745)

如果我在绘制到画布时尝试调整图像大小或尝试渲染整个图像,这并没有什么不同。

我的猜测是图像太大而无法渲染,但我找不到任何来源来验证这一点,也找不到任何东西可以解决我的问题。

我还对 Java 堆(使用 Eclipse 内存分析器)进行了分析,结果显示图像大小约为 376 MB。

所以基本上我的问题是: 1. 为什么我的程序会崩溃?是不是因为图太大了? 2. 如果我的图片太大,如何增加Java的可用空间?我的机器有 8GB RAM,显卡有 1GB RAM,所以

【问题讨论】:

您是否尝试增加堆大小? 是的,我尝试使用 4GB。而且我没有得到OutOfMemoryError,而是NullPointerException,这也意味着我的程序在抛出异常后仍在运行。它只是不能再渲染画布了。 是的,我知道!很奇怪你得到一个大图的NullPointerException 可能与一些错误跟踪问题有关RT-36386、RT-36540、RT-32258。我想你可以在javafx-jira.kenai.com 报告它,如果没有一个链接的问题看起来像重复(或者他们的解决方案似乎不令人满意)。 7Kx14K 是一个非常大的图像...... 相关Oracle forum discussion 可能有用。我的猜测是 8Kx8K 或 4Kx4K 图像适用于您的硬件/软件组合,但较大的图像可能不会。 【参考方案1】:

正如有人在 cmets 中指出的那样 - 只有 tp 4k/8k 纹理才能为您工作。这是因为 JavaFX 可能使用 GPU 来渲染图像。纹理大小限制可能是无法处理更大纹理的 GPU 或 GPU 驱动程序的限制。它不能创建这么大的纹理,所以它返回 null(这解释了 NullPointerException)。

修复它的唯一方法是避免使用如此大的纹理或获得更好的硬件来支持更大的纹理。使用软件渲染(可能真的很慢)可以通过使用以下参数运行 java 来修复它:

-Dprism.order=j2d

-Dprism.order=sw

但我不确定这是您想要实现的目标。

【讨论】:

【参考方案2】:

我可以用 2 个 VM 参数解决它:

-Dprism.order=sw
-Xmx1024m

这两个我都需要。

【讨论】:

【参考方案3】:

我用 VM-Arguments 为我解决了这个问题:

-Dprism.poolstats=true -Dprism.maxvram=500m -Dprism.order=sw -Djavafx.animation.fullspeed=true

【讨论】:

以上是关于渲染大图像时出现javafx NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

更改 JavaFX 选项卡顺序时出现 NullPointerException

JavaFX 11:创建标签时出现 IllegalAccessError

JavaFX 11:创建标签时出现 IllegalAccessError

运行 JavaFx 媒体应用程序时出现模块错误

使用 JavaFX 切换场景时出现 InvocationTargetException

在 JavaFX 中更新 ListView 时出现 IndexOutOfBoundsException