ImageIO 无法写入 JPEG 文件

发布于 2024-09-13 07:45:44 字数 1230 浏览 7 评论 0原文

我有一个 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

I have a BufferedImage I'm trying to write to a jpeg file, but my Java program throws an exception. I'm able to successfully save the same buffer to a gif and png. I've tried looking around on Google for solutions, but to no avail.

Code:

   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:

 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

筱果果 2024-09-20 07:45:44

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

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

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

OpenJDK does not have a native JPEG encoder. Try using Sun's JDK, or using a library (such as JAI).

AFAIK, regarding the "pinkish tint", Java saves the JPEG as ARGB (still with transparency information). Most viewers, when opening, assume the four channels must correspond to a CMYK (not ARGB) and thus the red tint.

If you import the image back to Java, the transparency is still there, though.

人事已非 2024-09-20 07:45:44

我在 OpenJDK 7 中遇到了同样的问题,我设法通过使用 TYPE_3BYTE_BGRimageType(而不是使用相同 OpenJDK 的 TYPE_4BYTE_ABGR)来解决此异常。

I had the same issue in OpenJDK 7 and I managed to get around this exception by using an imageType of TYPE_3BYTE_BGR instead of TYPE_4BYTE_ABGR using the same OpenJDK.

雅心素梦 2024-09-20 07:45:44

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

2019 answer: Make sure your BufferedImage does not have alpha transparency. JPEG does not support alpha, so if your image has alpha then ImageIO cannot write it to JPEG.

Use the following code to ensure your image does not have alpha transparancy:

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;
}
十年不长 2024-09-20 07:45:44

这是一些代码来说明@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();
}

Here is some code to illustrate @Thunder idea to change the image type to 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();
}
伤痕我心 2024-09-20 07:45:44

您会收到相同的错误

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?如何解决这个问题。

You get the same error

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)

if you are using a not supported Color Space (in my case CYMK). See How to convert from CMYK to RGB in Java correctly? how to solve this.

自由范儿 2024-09-20 07:45:44

当我获得的图像是 RenderedImage 时,我有一个变化,我使用的是矩形图像表示形式的 Raster,而不是复制字节数组。

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

根据您的需要,从 ColorModel 获取栅格可能会很有趣。

I had a variation when the image I got was a RenderedImage, and instead of copying the byte array, I'm using the Raster which is a rectangular image representation.

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

Depending on your needs it might be interesting to get the raster from the ColorModel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文