使用ImageIO.write写入jpg或jpeg图片时没有创建图片文件

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

重要提示:我正在使用JavaFX 12。

如果我将图片导出为png格式,该图片会显示在我的桌面上。但如果文件格式是jpeg之类的格式,则不会创建该图片。

以前,当我使用JavaFX 8时,使用上述代码保存为jpeg格式会导致图片变成粉红色调。现在在版本12中,什么也没发生。

那么我应该如何创建另一种格式(如jpeg)的图片呢?

我还检查了ImageIO支持的格式,返回结果如下:

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

你可以编辑你的问题并发布你正在使用的 VM 参数(即 --add-modules),或者你的 build.gradle/pom.xml 文件吗? - José Pereda
嗯...在JPEGImageWriterSpi.canEncode调试时返回false,因为ColorModel具有alpha值...虽然我对图像编码不太了解。 - kleopatra
2个回答

7
首先,我可以确认这种行为适用于JavaFX 13 ea版本13。这可能是一种简单的尝试修复一个旧问题,OP已经提到过(图像变成粉色),我很久以前就报告过这个问题。问题在于JPEG无法存储alpha信息,在过去,当带有alpha通道的图像作为JPEG写出时,输出只是混乱的。现在的解决方法是完全拒绝写出图像,而不是仅忽略alpha通道。
解决方法是制作一份显式指定没有alpha通道颜色模型的图像副本。
这里是原始的错误报告,其中还包含了解决方法:https://bugs.openjdk.java.net/browse/JDK-8119048 以下是更多信息,以简化转换: 如果您将此行添加到您的代码中:
BufferedImage awtImage = new BufferedImage((int)img.getWidth(), (int)img.getHeight(), BufferedImage.TYPE_INT_RGB);

然后将此对象作为第二个参数传递给SwingFXUtils.fromFXImage(img, awtImage),而不是null,这样就会自动完成所需的转换,并按预期写入JPEG文件。


1
此外,如果您没有可用的SwingFXUtils,并且您需要克隆一个没有alpha通道的BufferedImage到另一个BufferedImage中,您可以参考mipa的回答。
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();

这个答案解决了问题,现在图像已经写入文件,但是我的通常是白色背景变成了黑色。 - HopefullyHelpful
使用另一个带有Color参数的Graphics.drawImage方法。请参阅文档:“bgcolor是在图像的非不透明部分下绘制背景颜色。”尝试使用Color.WHITE。 - S. Doe
我已经尝试过了,但是我的图片背景似乎是透明的黑色,所以它仍然是黑色的,我需要手动将透明的黑色更改为不透明的白色。 - HopefullyHelpful

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