简体   繁体   English

ImageIO 无法写入 JPEG 文件

[英]ImageIO not able to write a JPEG file

I have a BufferedImage I'm trying to write to a jpeg file, but my Java program throws an exception.我有一个 BufferedImage 我正在尝试写入一个 jpeg 文件,但我的 Java 程序抛出异常。 I'm able to successfully save the same buffer to a gif and png.我能够成功地将相同的缓冲区保存为 gif 和 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

OpenJDK does not have a native JPEG encoder, try using Sun's JDK, or using a library (such as JAI OpenJDK没有原生JPEG编码器,尝试使用Sun的JDK,或使用库(如JAI)

AFAIK, regarding the "pinkish tint", Java saves the JPEG as ARGB (still with transparency information). AFAIK,关于“粉红色调”,Java将JPEG保存为ARGB(仍然具有透明度信息)。 Most viewers, when opening, assume the four channels must correspond to a CMYK (not ARGB) and thus the red tint. 大多数观众在打开时假设四个频道必须对应于CMYK(不是ARGB),因此必须是红色。

If you import the image back to Java, the transparency is still there, though. 如果将图像导回到Java,透明度仍然存在。

我有同样的问题在OpenJDK 7的,我设法通过使用得到这个例外各地imageTypeTYPE_3BYTE_BGR代替TYPE_4BYTE_ABGR使用相同的OpenJDK。

Here is some code to illustrate @Thunder idea to change the image type to TYPE_3BYTE_BGR这是一些代码来说明@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();
}

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). 如果你使用不支持的色彩空间(在我的情况下是CYMK)。 See How to convert from CMYK to RGB in Java correctly? 请参阅如何正确地在Java中将CMYK转换为RGB? how to solve this. 怎么解决这个问题。

2019 answer: Make sure your BufferedImage does not have alpha transparency. 2019回答:确保您的BufferedImage没有Alpha透明度。 JPEG does not support alpha, so if your image has alpha then ImageIO cannot write it to JPEG. JPEG不支持alpha,因此如果您的图像具有alpha,则ImageIO无法将其写入JPEG。

Use the following code to ensure your image does not have alpha transparancy: 使用以下代码确保您的图像没有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;
}

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.当我得到的图像是RenderedImage时,我有一个变化,而不是复制字节数组,我使用的是Raster ,它是一个矩形图像表示。

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 .根据您的需要,从ColorModel获取栅格可能会很有趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM