将Canvas转换为WritableImage的替代方案

8
我正在开发一个需要在JavaFX中比较大量图像数据的应用程序。为了进行比较,我需要获取图像像素的RGB数据。假设我需要比较的图片是Picture1Picture2。其中,Picture1是用户选择的输入图片,Picture2是我通过编程绘制的图形。
据我所知,在JavaFX中获取每个像素的RGB数据的唯一方法是使用ImagePixelReader。对于Picture1这样的输入图片来说,这没问题。但是,我需要在Picture2上进行绘制,而Picture2是一个Canvas(我使用多边形进行绘制,因为使用PixelWriter逐像素绘制有点复杂),并且没有PixelReader或类似功能的东西。因此,我的解决方案如下:
  1. 读取输入图片并创建Picture1
  2. 创建一个Canvas并进行绘制
  3. Canvas附加到场景中
  4. 对场景进行快照并创建可写入的图像Picture2
  5. 比较Picture1Picture2
因此,我有一个类似以下内容的方法:
public static WritableImage makeDrawableImage(Canvas in) {
     AnchorPane root = new AnchorPane(in);
     WritableImage out = new WritableImage((int)in.getWidth(), (int)in.getHeight());
     Scene sc = new Scene(root, in.getWidth(), in.getHeight());

     out = in.snapshot(null, null);

     return out;
}

然而,快照需要很长时间才能完成。 out 的值从未被分配。我不知道我做错了什么。
是否有其他方法可以将Canvas转换为ImageWritableImage?或者可能有一个库可以更容易地使用PixelWriter绘制多边形?
请对我温柔一点。这是我在Stack Overflow上的第一个问题,我不是真正的程序员也不是IT学生。我编写代码只是出于兴趣。
因此,在此提前感谢您。干杯。
1个回答

2
你可以使用这个方法创建画布的快照:
public static WritableImage pixelScaleAwareCanvasSnapshot(Canvas canvas, double pixelScale) {
    WritableImage writableImage = new WritableImage((int)Math.rint(pixelScale*canvas.getWidth()), (int)Math.rint(pixelScale*canvas.getHeight()));
    SnapshotParameters spa = new SnapshotParameters();
    spa.setTransform(Transform.scale(pixelScale, pixelScale));
    return canvas.snapshot(spa, writableImage);     
}

像素比例通常为1.0,除非您使用的是HiDPI屏幕。

它仍然不起作用 :( 我的问题出在 'out = in.snapshot(null, null);' 上。这需要很长时间。拍摄快照真的需要那么长时间吗? - Teguh Hidayat
你有什么问题?你的图片有多大? - mipa
显然你还在使用你的代码而不是我的。在我的代码中,没有一行是 'out = in.snapshot(null, null);' 对一个2000x2000的画布进行快照只需要几毫秒钟。 - mipa
return canvas.snapshot(spa, writableImage)没有返回任何东西。我认为这是因为它需要很长时间。是这样吗?画布的尺寸是600x1000。无论如何,谢谢。 - Teguh Hidayat
如果花费的时间太长了,那就有点可疑了。也许你已经在画布上绘制了太多内容,导致渲染还没有完成? - mipa
我找到了代码的问题。我刚刚意识到该方法在另一个线程上运行,因此“snapshot”无法工作。无论如何,感谢 mipa :) - Teguh Hidayat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接