如何将缓冲图像转换为图像,以及反之?

24

实际上,我正在开发一款图像编辑软件,现在我想将缓冲图像转换为:

  BufferedImage buffer = ImageIO.read(new File(file));

转换为图片,即以以下格式:

  Image image  = ImageIO.read(new File(file));

是否有可能这样做?如果是,那么如何实现?

6个回答

30

BufferedImage是图像(Image)类型的一种,因此你在第二行所做的隐式转换可直接编译。如果你知道一个Image实际上就是一个BufferedImage,那么你需要像这样显式地进行强制类型转换:

Image image = ImageIO.read(new File(file));
BufferedImage buffered = (BufferedImage) image;

因为BufferedImage扩展自Image,所以它可以适应Image容器。然而,任何图像都可以适应其中,包括不是BufferedImage的图像,因此如果类型不匹配,则可能在运行时出现ClassCastException,因为BufferedImage除非扩展了BufferedImage,否则不能保存任何其他类型。


实际上我正在尝试旋转我的图像,我可以通过使用以下形式的图像来完成:Image image = ImageIO.read(new File(file)); 但是当给定缓冲图像时,我不知道该怎么做? - Arizvi
3
把“Image”说成是BufferedImage就像把猫叫做动物一样 - 只因它是只猫并不意味着它不是动物。 BufferedImage 是一种 Image,但不是其他类型的 Image - 通常情况下,任何需要 Image 的东西都可以使用 BufferedImage。 - MetroidFan2002

11

例如:假设您有一个要缩放的“图像”,您可能需要一个缓冲图像,并且可能仅从“Image”对象开始。所以我认为这样可以... AVATAR_SIZE是我们希望图像达到的目标宽度:

Image imgData = image.getScaledInstance(Constants.AVATAR_SIZE, -1, Image.SCALE_SMOOTH);     

BufferedImage bufferedImage = new BufferedImage(imgData.getWidth(null), imgData.getHeight(null), BufferedImage.TYPE_INT_RGB);

bufferedImage.getGraphics().drawImage(imgData, 0, 0, null);

8

实际上我正在尝试旋转我的图像,我可以通过使用以下形式的图像来完成:Image image = ImageIO.read(new File(file)); 但是当给定缓冲图像时,我不知道该怎么做? - Arizvi

7
你可以尝试保存(或编写)缓冲图像并进行更改,然后将其作为图像打开。

编辑:

try {
    // Retrieve Image
    BufferedImage buffer = ImageIO.read(new File("old.png"));;
    // Here you can rotate your image as you want (making your magic)
    File outputfile = new File("saved.png");
    ImageIO.write(buffer, "png", outputfile); // Write the Buffered Image into an output file
    Image image  = ImageIO.read(new File("saved.png")); // Opening again as an Image
} catch (IOException e) {
    ...
}

1
我不理解。我没有明白你的意思... :( - Arizvi

5

正确的方法是使用SwingFXUtils.toFXImage(bufferedImage,null)将BufferedImage转换为JavaFX Image实例,使用SwingFXUtils.fromFXImage(image,null)进行反向操作。

可选地,第二个参数可以是WritableImage以避免进一步的对象分配。


这个问题很老,早于JavaFX 2,所以它应该是指 java.awt.Image 而不是 java.scene.image.Image。然而,这个答案仍然有用,因为如果有人遇到这个问题并真的想将 BufferedImage 转换为 JavaFX 图像,这确实是正确的方法。 - jewelsea
我的错,我只是在想,因为所有的解决方案都会写入磁盘,这在性能方面是不可取的。 - throws_exceptions_at_you

5
只是一些信息:让我们都记住,Image类实际上是一个抽象类,使用BufferedImage引用变量只存储或返回任何对象的内存地址。
此外,静态java.awt.image.imageIO的read()方法返回一个BufferedImage对象,因此毫无疑问,在该对象上使用运算符/表达式instanceof BufferedImage将返回true。
事实上,作为抽象类,Image类具有以下方法签名:
1. public abstract Graphics getGraphics() 2. public abstract ImageProducer getSource()
我强调,实际的Image变量仅保存具体Image子类对象的内存地址,几乎像C,C++,Ada等语言中的指针。
如果您已经介绍或熟悉了这些语言,并且还熟悉Java接口实例,例如Runnable,javax.sound.Clip,AWT的Shape等。 请注意,Image具有:public abstract Image getScaledInstance(...)-您明白了吗? (当然,在2D图形编程中,缩放与调整大小是可互换的,其中需要精度)。
但是,在不可能的情况下,当ImageIO方法返回!(instanceof BufferedImage)时,只需创建一个新的BufferedImage对象,并将其apassed给其构造函数参数中的ImgObjNotInstncfBufImg之一。 然后,按(合理的)意愿在代码逻辑中操纵它。
无论如何,Affine Transform类适用于将形状和图像转换为其缩放,旋转,重新定位等形式,因此我建议您学习如何使用“仿射变换”。
请注意,您可以操纵此类图像的实际像素-这是另一个必须从技术词汇表中引用的技术2D图形术语-可能需要Java二进制blitwise操作方式的练习技能,在存储单个颜色属性的Image缓冲区类型中,每个alpha和RGB值各占32字节的紧凑组合。
我怀疑您将在对图像进行分层时使用它。 因此,最后的理性是,您只参考BufferedImage与抽象Image,并且如果您的Image对象尚未是BufferedImage,则可以仅基于与之相关但非BufferedImage实例创建一个图像,而无需担心任何转换,强制转换,自动装箱或其他事项; 操作BufferedImage实际上意味着操作也指向其底层根图像数据承载对象的对象。

好的,完成了; 我认为我已经解决并分解出你可能认为面临的死锁问题。就像我所说的,在Java中抽象类和接口非常类似于其他语言中称为指针的低级、更接近硬件操作符。


我老实说有几次不太明白你的意思。感觉你这段话:“但在一个不可能的情况下,当ImageIO方法返回!(instanceof BufferedImage)时,只需创建一个新的BufferedImage对象,并将此ImgObjNotInstncfBufImg传递给其中一个构造函数参数。然后,在(合理的)逻辑中操作它。”已经包含了完整的答案,但我还是不太理解。你解释了很多,但对于实际的答案却讲得比较快... - Draeven

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