ImageIO 无法写入 JPEG 文件

问题描述 投票:0回答:6

我有一个 BufferedImage,我试图写入 jpeg 文件,但我的 Java 程序抛出异常。我能够成功地将相同的缓冲区保存为 gif 和 png。我尝试在 Google 上寻找解决方案,但无济于事。

代码:

   File outputfile = new File("tiles/" + row + ":" + col + ".jpg");
   try {
       ImageIO.write(mapBufferTiles[row][col], "jpg", outputfile);
   } catch (IOException e) {
        outputfile.delete();
        throw new RuntimeException(e);
   }

例外:

 Exception in thread "main" java.lang.RuntimeException: javax.imageio.IIOException: Invalid argument to native writeImage
 at MapServer.initMapBuffer(MapServer.java:90)
 at MapServer.<init>(MapServer.java:24)
 at MapServer.main(MapServer.java:118)
 Caused by: javax.imageio.IIOException: Invalid argument to native writeImage
 at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeImage(Native Method)
 at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeOnThread(JPEGImageWriter.java:1055)
 at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:357)
 at javax.imageio.ImageWriter.write(ImageWriter.java:615)
 at javax.imageio.ImageIO.doWrite(ImageIO.java:1602)
 at javax.imageio.ImageIO.write(ImageIO.java:1526)
 at MapServer.initMapBuffer(MapServer.java:87)
 ... 2 more
java image jpeg javax.imageio
6个回答
47
投票

OpenJDK 没有原生 JPEG 编码器。尝试使用 Sun 的 JDK,或使用库(例如 JAI)。

AFAIK,关于“粉红色调”,Java 将 JPEG 保存为 ARGB(仍然带有透明度信息)。大多数观看者在打开时会假设四个通道必须对应于 CMYK(而不是 ARGB),从而对应于红色色调。

如果将图像导入回 Java,透明度仍然存在。


40
投票

我在 OpenJDK 7 中遇到了同样的问题,我设法通过使用

imageType
TYPE_3BYTE_BGR
来解决此异常,而不是使用相同的 OpenJDK 的
TYPE_4BYTE_ABGR


25
投票

2019 答案:确保您的 BufferedImage 没有 alpha 透明度。 JPEG 不支持 Alpha,因此如果您的图像有 Alpha,则 ImageIO 无法将其写入 JPEG。

使用以下代码确保您的图像没有 Alpha 透明度:

static BufferedImage ensureOpaque(BufferedImage bi) {
    if (bi.getTransparency() == BufferedImage.OPAQUE)
        return bi;
    int w = bi.getWidth();
    int h = bi.getHeight();
    int[] pixels = new int[w * h];
    bi.getRGB(0, 0, w, h, pixels, 0, w);
    BufferedImage bi2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    bi2.setRGB(0, 0, w, h, pixels, 0, w);
    return bi2;
}

8
投票

这里有一些代码来说明@Thunder将图像类型更改为TYPE_3BYTE_BGR的想法

try {
  BufferedImage input = ImageIO.read(new File("input.png"));
  System.out.println("input image type=" + input.getType());
  int width = input.getWidth();
  int height = input.getHeight();
  BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
  int px[] = new int[width * height];
  input.getRGB(0, 0, width, height, px, 0, width);
  output.setRGB(0, 0, width, height, px, 0, width);
  ImageIO.write(output, "jpg", new File("output.jpg"));
} catch (Exception e) {
  e.printStackTrace();
}

1
投票

您遇到同样的错误

Caused by: javax.imageio.IIOException: Invalid argument to native writeImage
at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeOnThread(JPEGImageWriter.java:1055)

如果您使用的是不受支持的色彩空间(在我的例子中为 CYMK)。请参阅如何在Java中正确从CMYK转换为RGB?如何解决这个问题。


0
投票

当我得到的图像是

RenderedImage
时,我有一个变化,我没有复制字节数组,而是使用
Raster
,它是一个矩形图像表示。

var newBufferedImage = new BufferedImage(
    renderImg.getWidth(),
    renderImg.getHeight(),
    BufferedImage.TYPE_INT_RGB
);
renderImg.copyData(newBufferedImage.getRaster());

根据您的需求,从

ColorModel
获取光栅可能会很有趣。

© www.soinside.com 2019 - 2024. All rights reserved.