【问题标题】:Save ReadableByteChannel as PNG将 ReadableByteChannel 保存为 PNG
【发布时间】:2021-01-11 14:33:17
【问题描述】:

我有一个ReadableByteChannel,其中包含一个图像(从 URL 或文件获取)。我最终将 Channel 写入一个文件,代码如下:

final FileOutputStream fileOutputStream = new FileOutputStream(outImageName);
fileOutputStream.getChannel().transferFrom(imageByteChannel, 0, Long.MAX_VALUE);
fileOutputStream.close();

由于不清楚图像是png 还是jpeg 还是...我想确定并将其保存为png。我知道我可以使用ImageIO.write(buffImg, outImageName, "png");

但不知何故,这要求buffImgRenderedImage,这就提出了如何获得它的问题?

有没有比使用ImageIO 从文件系统读取文件并将其写为png 更简单的解决方案?可以直接在内存中转换吗?

另外还有一个问题:有没有办法告诉ImageIO 摆脱 AlphaChannel(=透明)?

【问题讨论】:

  • 我会选择 (1) - 但我遇到的主要问题是我不知道如何使用 ImageIO 而不先将 OutputStream 写入 File 然后阅读从那里开始。我宁愿不写不读就这样做——即直接。
  • 如果可以,获取InputStream 或底层FileURL 而不是ReadableByteChannel,因为ImageIO.read(..) 支持所有这些类型作为输入。如果不可能,您可以使用Channels.newInputStream(..) 获取InputStream,您可以将其传递给ImageIO.read(...)。无需先写信给File
  • 您也可以以同样的方式回写到OutputStream 或可写Channel,而无需通过文件。
  • ImageIO.read(Channels.newInputStream(ReadableByteChannel)) 的想法做到了。我不知道如何将Channel 转换为另一个。谢谢。
  • @LeO 我在上面的评论中添加了一些代码并作为答案发布 + 添加了关于摆脱 alpha 通道 + 写入文件的部分。

标签: java javax.imageio


【解决方案1】:

如果可以,我建议使用InputStream 或底层FileURL 对象而不是ReadableByteChannel,因为ImageIO.read(..) 直接支持所有这些类型作为输入。

如果不可能,您可以使用Channels.newInputStream(..) 从字节通道获取InputStream,然后传递给ImageIO.read(...)。无需先写入文件。

代码:

ReadableByteChannel channel = ...; // You already have this
BufferedImage image = ImageIO.read(Channels.newInputStream(channel))

要消除任何不需要的透明度,您可以这样做:

BufferedImage opaque = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = opaque.createGraphics();
try {
    g.setColor(Color.WHITE); // Or any other bg color you like
    g.fillRect(0, 0, image.getWidth(), image.getHeight());

    g.drawImage(image, 0, 0, null);
}
finally {
    g.dispose();
}

您现在可以将图像以 PNG 格式写入文件或流:

if (!ImageIO.write(opaque, "PNG", new File(outputFile)) {
    // TODO: Handle odd case where the image could not be written
}

【讨论】:

  • 有趣的是,ImageIO.write 重新转换为 true/false。是的,这是有道理的......但我不确定如果失败该怎么办。无论如何,谢谢你的完整答案(我没有这样做;-))。
  • @LeO 是的,很多人都忘记了这一点,并想知道为什么什么也没发生...格式支持TYPE_3BYTE_BGR 格式(至少在Oracle 或标准OpenJDK 变体上),因此您可以安全地断言它,或者在那里抛出异常。它不应该发生。
猜你喜欢
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-16
  • 2012-10-29
  • 2010-11-22
相关资源
最近更新 更多