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.
希望它对某人有帮助。