Java将图像转换为BuffereImage

Java将图像转换为BuffereImage,java,image,casting,bufferedimage,Java,Image,Casting,Bufferedimage,StackOverflow上已经有类似的问题,公认的答案是“铸造”: 在我的程序中,我尝试: 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.getScal

StackOverflow上已经有类似的问题,公认的答案是“铸造”:

在我的程序中,我尝试:

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

显然,铸造不起作用。
问题是:将图像转换为BuffereImage的正确方法是什么


如果您要返回一个
sun.awt.image.ToolkitImage
,则可以将该图像强制转换为该图像,然后使用获取
缓冲区图像

因此,您只需执行以下操作,而不是最后一行代码:

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

处理此问题的一种方法是创建新的BuffereImage,并告诉其图形对象将缩放图像绘制到新的BuffereImage中:

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);

如果你使用Kotlin,你可以像Sri Harsha Chilakapati建议的那样为图像添加扩展方法

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()

如果要缩放缓冲图像,请尝试此[[1]:请注意,不是编译器说的。您实际上看到的是运行时错误…不是编译错误。您是对的。感谢您指出这一点。我将相应地编辑问题。@user902383,即使他们没有直接回答我的问题-这些也是很好的解决方案。OP:Method
ImageIO的小问题。read(File)
通过签名返回一个
buffereImage
。()无需先指定一个
Image
变量,然后强制转换为type
buffereImage
。这可能会让阅读代码的人感到困惑。永远不要忘记处理创建的图形实例如何“处理创建的图形界面”?BuffereImage构造函数中的类型是否应与getScaledInstance中的类型匹配?不,该类型类似于ARGB或RGBA,即图像数据的内部存储方式-选择应用程序最自然的类型;键入BuffereImage时只需查看自动完成。[自动完成]要查看所有选项,1)不允许使用
sun
包中的类。它们不保证在非Oracle JDK中可用。2)方法
getBufferedImage()
仅在缓冲映像由
TookitImage
内部生成时有效。大多数情况下(99%)它不是,所以返回值是代码> null < /C> > @ SRiHARSHIACHACKAPATAT<代码>使用java时不应该担心内存。< /Cuff>判断java应用程序的平均内存消耗,其他开发人员肯定不会担心内存。@ Tom Asz ZATO在我看来,你来自C++世界,思考。重用图像数据像素的内存。我的意思是,在这种情况下,不需要担心内存,因为GC将在Java中处理它。@SriHarshaChilakapati,这样垃圾收集器就不会消耗任何资源?GC只会从内存周围的代码中节省内存。它不会消除硬件限制。不是吗如果未加载
图像
,his将不起作用,因为
getWidth(null)
getHeight(null)
将返回
-1
,在这种情况下,我必须使用
缓冲图像。键入\u INT\u RGB
而不是ARGB以获得正确的缩略图颜色
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()