将BufferedImage转换为JavaFX图像

38

我从主显示器截屏了一张图片,现在想将其添加到一个Java FX ImageView中:

@FXML
protected ImageView screenshot() throws AWTException, IOException {
    Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
    BufferedImage capture = new Robot().createScreenCapture(screenRect);
    ImageView imageView = new ImageView();
    Image image = capture; //Error
    imageView.setImage(image);
    return imageView;
}

我正在尝试将BufferedImage capture设置为javafx.scene.image.Image image,但类型不兼容,我也无法进行强制转换。我该如何纠正这个问题?

3个回答

73

您可以使用

Image image = SwingFXUtils.toFXImage(capture, null);

5
这个解决方案的表现如何?有没有一种方法可以直接创建javafx.scene.image.Image而不必先创建BufferedImage - Halil
2
当我来到这里时,我有完全相同的问题。 我查看了SwingFXUtils的实现,发现如果创建一个JavaFX WritableImage,确实可以做到这一点。 在这种情况下,您可以获取其PixelWriter,并将数据缓冲区写入图像。 这非常快速,并且类似于使用BufferedImage所做的事情。 我在此方面取得了非常好的性能表现。 - Erik Stens

9
通常在Java9或更高版本中,最好的选择是使用Image image = SwingFXUtils.toFXImage(capture, null);。但是在JavaFX中,尤其是在性能较低的设备上,您可以使用这种技术来提高性能。该技术已在Java8中进行了测试。
private static Image convertToFxImage(BufferedImage image) {
    WritableImage wr = null;
    if (image != null) {
        wr = new WritableImage(image.getWidth(), image.getHeight());
        PixelWriter pw = wr.getPixelWriter();
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                pw.setArgb(x, y, image.getRGB(x, y));
            }
        }
    }

    return new ImageView(wr).getImage();
}

4
这是什么魔法?对我来说,这看起来像是逐个复制每个像素的最慢的方法。 - mipa
看起来不太可靠,但请相信我,它的速度非常快。我在树莓派设备上进行了测试(即使在慢速互联网环境下也是如此),并且在Windows和Linux(Ubuntu)上都进行了测试,其行为都是相同的(始终使用jre1.8中的JavaFX)。我需要找到另一个解决方案,这就是我找到的。使用最适合您的解决方案。 - Dan
如果您只想将byte[]转换为JavaFX图像,则可以跳过创建BufferedImage - 请参见最佳答案下用户“FinalArt2005”的评论。 - Nighty42

2

将一个 1080x2280 (TYPE_3BYTE_BGR) 的 java.awt.image.BufferedImage 转换成 javafx.scene.image.Image 比预期的更困难。

Reimeus 的解决方案运行时间为15毫秒

Dan 的解决方案运行时间为210毫秒

我的解决方案运行时间为6毫秒

private Image getImage(BufferedImage img){
    //converting to a good type, read about types here: https://openjfx.io/javadoc/13/javafx.graphics/javafx/scene/image/PixelBuffer.html
    BufferedImage newImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
    newImg.createGraphics().drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null);

    //converting the BufferedImage to an IntBuffer
    int[] type_int_agrb = ((DataBufferInt) newImg.getRaster().getDataBuffer()).getData();
    IntBuffer buffer = IntBuffer.wrap(type_int_agrb);

    //converting the IntBuffer to an Image, read more about it here: https://openjfx.io/javadoc/13/javafx.graphics/javafx/scene/image/PixelBuffer.html
    PixelFormat<IntBuffer> pixelFormat = PixelFormat.getIntArgbPreInstance();
    PixelBuffer<IntBuffer> pixelBuffer = new PixelBuffer(newImg.getWidth(), newImg.getHeight(), buffer, pixelFormat);
    return new WritableImage(pixelBuffer);
}

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