将 Image 转换为 BufferedImage

在 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 的正确方法是什么?

184546 次浏览

From a Java Game Engine:

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

If you are getting back a sun.awt.image.ToolkitImage, you can cast the Image to that, and then use getBufferedImage() to get the BufferedImage.

So instead of your last line of code where you are casting you would just do:

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

One way to handle this is to create a new BufferedImage, and tell it's graphics object to draw your scaled image into the new 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);

That should do the trick without casting.

If you use Kotlin, you can add an extension method to Image in the same manner Sri Harsha Chilakapati suggests.

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
}

And use it like this:

myImage.toBufferedImage()