7

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
Ricky
  • 553
  • 6
  • 21
  • Can you edit your question and post the VM arguments you are using (i.e. `--add-modules`), or your build.gradle/pom.xml files? – José Pereda Aug 27 '19 at 12:00
  • hmm ... did debug into the JPEGImageWriterSpi.canEncode: returns false because the ColorModel has an alpha value .. don't know enough about image encoding, though – kleopatra Aug 27 '19 at 12:08

2 Answers2

7

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.

mipa
  • 10,369
  • 2
  • 16
  • 35
1

Additionally to the answer of mipa and in the case that you do not have SwingFXUtils available, you could clone the BufferedImage into another BufferedImage without alpha channel:

BufferedImage withoutAlpha = new BufferedImage(
    (int) originalWithAlpha.getWidth(),
    (int) originalWithAlpha.getHeight(), 
    BufferedImage.TYPE_INT_RGB);
Graphics g = withoutAlpha.getGraphics();
g.drawImage(originalWithAlpha, 0, 0, null);
g.dispose();
S. Doe
  • 685
  • 1
  • 6
  • 25
  • This answer kind of fixed the problem, an image is now written to the file, but now my normally white background is black. – HopefullyHelpful Dec 14 '20 at 17:37
  • Use one of the other Graphics.drawImage methods with a Color parameter. See documentation: "bgcolor the background color to paint under the non-opaque portions of the image." Try Color.WHITE. – S. Doe Dec 15 '20 at 21:01
  • I did, but it seems that the background of my image is transparent black, so it still is black, I needed to manually change the transparent black to opaque white. – HopefullyHelpful Dec 15 '20 at 21:11