JavaFX上Canvas.snapshot()的替代方案

JavaFX上Canvas.snapshot()的替代方案

问题描述:

我正在JavaFX中使用 Canvas 开发一个小图形引擎。在某些时候,我不得不渲染一个关闭屏幕的图像,然后使用它的 GraphicContext 在我的主画布上打印。

我正在使用此代码现在:

I'm developing a little graphic engine using Canvas in JavaFX. In some point I had to render an off screen image, and then print it on my primary canvas using its GraphicContext.
I'm using this code right now:

private Canvas offScreenCanvas;
private GraphicsContext offScreenGraphic;
private SnapshotParameters parameters;
private WritableImage offScreenImage;

[...]

offScreenCanvas = new Canvas(WIDTH, HEIGHT);
offScreenGraphic = offScreenCanvas.getGraphicsContext2D();

parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);

[...]

offScreenImage = offScreenCanvas.snapshot(parameters, offScreenImage);
graphic.setGlobalBlendMode(BlendMode.HARD_LIGHT);
graphic.drawImage(offScreenImage, 0, 0);
graphic.setGlobalBlendMode(BlendMode.SRC_OVER);

我的问题是方法 snaphot()在每次执行中花费太多时间,约14毫秒。我需要至少以60fps的速度更新画布,所以这几乎占用了我必须画的所有时间。

My problem is the method snaphot() takes too much time, ~14ms, in each execution. I need to update the canvas at least at 60fps, so this consumes practically all the time I have to draw.

还有另一种方法来获得画布来自画布的WritableImage ?也许是另一个不同的过程?

Is there another way to get an Image or WritableImage from a canvas? Maybe another different process?

这是获得视觉等效结果的另一种方法,不会降低性能。

This is another method to obtain a visual equivalent result, without reduce performance.

我使用了 java.awt clases,而不是JavaFX clases。创建 java.awt.image.BufferedImage 提供了获取 java.awt.Graphics2D 的可能性可以使用其他方法绘制。这里的主要问题是绘制大图像会消耗大量时间使用此库,但您可以创建缩放图像。在我的例子中,我创建了一个四分之一大小 BufferedImage ,并且我使用该比例因子绘制了所有对象。

I have used java.awt clases, instead of JavaFX clases. The creation of a java.awt.image.BufferedImage offers the possibility to get a java.awt.Graphics2D where you can draw using other methods. The main problem here is that draw big images consumes a lot of time using this libraries, but you can create a scaled image. In my case, I have created a quarter-size BufferedImage, and I have drawn all the objects using that scale factor.

在绘制过程结束时,只需将 BufferedImage 转换为 javafx.scene.image.Image ,使用:

At the end of the draw process, just convert the BufferedImage, to a javafx.scene.image.Image, using:

 SwingFXUtils.WritableImage toFXImage(BufferedImage bimg, WritableImage wimg);

然后使用以下方法在主画布上打印:

Then print it on the main canvas using:

 graphic.drawImage(Image image, 0, 0, WIDTH, HEIGHT);

用图像填充所有画布。

To fill all the canvas with the image.

最后,比例因子是可配置的,因此如果您需要详细的图像,只需使用更高的值。对我来说,25%大小的图像就足够了,因为我正在绘制渐变。现在,绘制图像需要1-3毫秒,这比以前好多了。

Finally, the scale factor is configurable, so if you need a detailed image, just use a higher value. For me, a 25-percent-size image is enough because I am drawing gradients. Now, it takes 1-3ms to draw the image, this is much better than before.

希望它对某人有帮助。