javafxjpegjavax.imageio

Writing jpg or jpeg image with ImageIO.write does not create image file


I recreated the issue in a minimal form:

MAIN:

public class ImageIOMain extends Application {

    @Override
    public void start(Stage stage) throws Exception{
        Scene scene = new Scene(new StackPane(), 800.0, 600.0);

        stage.setScene(scene);
        stage.show();

        WritableImage img = scene.snapshot(null);

        //Image file created on desktop
        ImageIO.write(SwingFXUtils.fromFXImage(img, null), "png", new File("D:\\Desktop\\test.png"));

        //Image file NOT created on desktop
        ImageIO.write(SwingFXUtils.fromFXImage(img, null), "jpeg", new File("D:\\Desktop\\test.jpeg"));
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Important: I'm using JavaFX 12.

If I export an image as png the image shows up on my desktop. If the file format is for example jpeg then the image is not created.

In the past when I used JavaFX 8 saving as jpeg using the above code caused the image to became pink toned. Now in version 12 nothing happens.

So how can I create an image which format is not png but something else like jpeg?

I also checked ImageIO supported formats which returns these:

JPG, jpg, tiff, bmp, BMP, gif, GIF, WBMP, png, PNG, JPEG, tif, TIF, TIFF, wbmp, jpeg

Solution

  • First of all I can confirm this behaviour for JavaFX 13 ea build 13. This was probably a very simplistic attempt to fix an old bug which the OP has already mentioned (image turning pink) which I reported a long time ago. The problem is that JPEGS cannot store alpha information and in the past the output was just garbled when an image with an alpha channel was written out as a JPEG. The fix now just refuses to write out the image at all instead of just ignoring the alpha channel.

    A workaround is to make a copy of the image where you explicitly specify a color model without alpha channel.

    Here is the original bug report which also contains the workaround: https://bugs.openjdk.java.net/browse/JDK-8119048

    Here is some more info to simplify the conversion: If you add this line to your code

    BufferedImage awtImage = new BufferedImage((int)img.getWidth(), (int)img.getHeight(), BufferedImage.TYPE_INT_RGB);
    

    and then call SwingFXUtils.fromFXImage(img, awtImage) with this as the second parameter instead of null, then the required conversion will be done automatically and the JPEG is written as expected.