Java将图像转换为BufferedImage


82

在StackOverflow上已经存在类似此链接的问题,并且可接受的答案是“广播”:

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

在我的程序中,我尝试:

final float FACTOR  = 4f;
BufferedImage img = ImageIO.read(new File("graphic.png"));
int scaleX = (int) (img.getWidth() * FACTOR);
int scaleY = (int) (img.getHeight() * FACTOR);
Image image = img.getScaledInstance(scaleX, scaleY, Image.SCALE_SMOOTH);
BufferedImage buffered = (BufferedImage) image;

不幸的是,我得到运行时错误:

sun.awt.image.ToolkitImage无法转换为java.awt.image.BufferedImage

显然,投射不起作用。
问题是:将Image转换为BufferedImage的正确方法是(或存在)什么?


如果你想扩展缓冲图像,试试这个试试这个[ stackoverflow.com/questions/4216123/... [1]:stackoverflow.com/questions/4216123/...
user902383

7
记录下来,并不是说编译器在说。您实际上看到的是运行时错误,而不是编译错误。
斯蒂芬·C

1
你是对的。感谢您指出了这一点。我将相应地编辑问题。
Arek Wilk 2012年

@ user902383即使他们没有直接回答我的问题,这些也是很好的解决方案。
Arek Wilk 2012年

OP的小物件:方法通过其签名ImageIO.read(File)返回a BufferedImage。(参考)不需要先分配给Image变量,然后将其强制转换为type BufferedImage。这可能会使人们阅读您的代码感到困惑。
kevinarpe

Answers:


123

Java游戏引擎

/**
 * Converts a given Image into a BufferedImage
 *
 * @param img The Image to be converted
 * @return The converted BufferedImage
 */
public static BufferedImage toBufferedImage(Image img)
{
    if (img instanceof BufferedImage)
    {
        return (BufferedImage) img;
    }

    // Create a buffered image with transparency
    BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);

    // Draw the image on to the buffered image
    Graphics2D bGr = bimage.createGraphics();
    bGr.drawImage(img, 0, 0, null);
    bGr.dispose();

    // Return the buffered image
    return bimage;
}

6
@SriHarshaChilakapatiYou shouldn't be worrying about the memory when using Java.从Java应用程序的平均内存消耗来看,其他开发人员绝对不用担心内存。
托马什Zato -恢复莫妮卡

1
@TomášZato在我看来,您来自C ++领域,正在考虑重用图像数据像素的内存。我的意思是说,在这种情况下,无需担心内存,因为GC将使用Java来处理它。
Sri Harsha Chilakapati

2
@SriHarshaChilakapati所以垃圾收集器不会消耗任何资源?GC仅从周围的代码中保存您。它不会根除硬件限制。
Andrew Sannier

5
如果Image尚未加载,则此方法将不起作用,因为在这种情况下,getWidth(null)否则getHeight(null)将返回-1
Dims 2015年

1
我必须使用BufferedImage.TYPE_INT_RGBARGB代替ARGB来获得缩略图的颜色
Stephanie

20

一种解决方法是创建一个新的BufferedImage,并告诉它的图形对象将缩放后的图像绘制到新的BufferedImage中:

final float FACTOR  = 4f;
BufferedImage img = ImageIO.read(new File("graphic.png"));
int scaleX = (int) (img.getWidth() * FACTOR);
int scaleY = (int) (img.getHeight() * FACTOR);
Image image = img.getScaledInstance(scaleX, scaleY, Image.SCALE_SMOOTH);
BufferedImage buffered = new BufferedImage(scaleX, scaleY, TYPE);
buffered.getGraphics().drawImage(image, 0, 0 , null);

那应该在不铸造的情况下完成。


2
永远不要忘记处理创建的图形实例
Sri Harsha Chilakapati 2012年

如何“处理创建的图形界面”?
水牛城

BufferedImage构造函数中的类型是否应该与getScaledInstance中的类型匹配?
Drazen Bjelovuk 2013年

不,TYPE类似于ARGB或RGBA,是内部存储图像数据的方式-选择对您的应用程序最自然的感觉;只需在键入BufferedImage时查看您的自动填充即可。[自动填充]可查看所有选择
salbeira

3

如果返回a sun.awt.image.ToolkitImage,则可以将Image转换为该图像,然后使用getBufferedImage()获取BufferedImage

因此,您只需执行以下操作即可:

BufferedImage buffered = ((ToolkitImage) image).getBufferedImage();

7
1)使用sun包中的类是不满意的。不保证它们在非Oracle JDK中可用。2)该方法getBufferedImage()仅在缓冲图像是由内部生成的情况下才有效TookitImage。大多数情况下(99%)并非如此,因此返回值为null来源参考
kevinarpe

3

如果使用Kotlin,则可以按照Sri Harsha Chilakapati建议的相同方式向Image添加扩展方法。

fun Image.toBufferedImage(): BufferedImage {
    if (this is BufferedImage) {
        return this
    }
    val bufferedImage = BufferedImage(this.getWidth(null), this.getHeight(null), BufferedImage.TYPE_INT_ARGB)

    val graphics2D = bufferedImage.createGraphics()
    graphics2D.drawImage(this, 0, 0, null)
    graphics2D.dispose()

    return bufferedImage
}

并像这样使用它:

myImage.toBufferedImage()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.