38

I have an image I screenshot from the primary monitor and I want to add it to a Java FX ImageView as so:

@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; } 

I'm trying to set the BufferedImage capture to javafx.scene.image.Image image but the types are incompatible nor am I able to cast it. How can I rectify this?

3 Answers 3

76

You can use

Image image = SwingFXUtils.toFXImage(capture, null); 
Sign up to request clarification or add additional context in comments.

2 Comments

Can you comment about the performance of this solution? Is there a way to directly create javafx.scene.image.Image without first creating BufferedImage?
I had the exact same question when I got here. I looked in the implementation of SwingFXUtils and saw it's indeed possible if you create a JavaFX WritableImage. In that case you can get its PixelWriter and just write a data buffer to the image. This is very fast and similar to what you'd do with a BufferedImage. I got very good performance out of this.
9

normally the best choice is Image image = SwingFXUtils.toFXImage(capture, null); in java9 or bigger.... but in matter of performance in javafx, also in devices with low performance, you can use this technique that will do the magic, tested in 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(); } 

3 Comments

What kind of magic is that? For me this looks like the slowest possible solution to copy over any single pixel individually.
looks like that but beleive me, it works fast, I test it in Raspian devices (slow performance also in a slow internet) and in both windos a linux (ubuntu), the behavior was the same (always using javafx from jre1.8). I needed to find another solution and this is what I found. use the soltion that best suits you
You can skip the creation of the BufferedImage if you just want to convert a byte[] to a JavaFX image - see the comment of the user "FinalArt2005" under the best answer.
3

converting a 1080x2280 (TYPE_3BYTE_BGR) java.awt.image.BufferedImage into a javafx.scene.image.Image turned out to be harder than expected.

the solution of Reimeus ran in 15ms

the solution of Dan ran in 210ms

my solution runs in 6ms

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); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.