【问题标题】:Java converting Image to BufferedImageJava 将 Image 转换为 BufferedImage
【发布时间】:2012-11-16 07:32:53
【问题描述】:

StackOverflow 上已经有类似link 的问题,并且接受的答案是“casting”:

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 即使他们没有直接回答我的问题 - 这些也是很好的解决方案。
  • 对 OP 的小事:方法 ImageIO.read(File) 通过其签名返回 BufferedImage。 (Reference) 无需先赋值给Image 变量,然后再转换为BufferedImage 类型。这可能会使阅读您的代码的人感到困惑。

标签: java image casting bufferedimage


【解决方案1】:

来自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;
}

【讨论】:

  • @SriHarshaChilakapati You shouldn't be worrying about the memory when using Java. 从 Java 应用程序的平均内存消耗来看,其他开发者绝对不会担心内存问题。
  • @TomášZato 在我看来,您似乎来自 C++ 世界,正在考虑重用图像数据像素的内存。我之前的评论是指在这种情况下无需担心内存,因为 GC 会在 Java 中处理它。
  • @SriHarshaChilakapati 所以垃圾收集器不消耗任何资源? GC 只会将你从 code 周围的内存中拯救出来。它不会消除硬件限制。
  • 如果Image 尚未加载,这将不起作用,因为getWidth(null)getHeight(null) 在这种情况下将返回-1
  • 我必须使用 BufferedImage.TYPE_INT_RGB 而不是 ARGB 才能正确显示缩略图的颜色
【解决方案2】:

处理这个问题的一种方法是创建一个新的 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);

不用强制转换就可以解决问题。

【讨论】:

  • 永远不要忘记处理创建的图形实例
  • 如何“处理创建的图形界面”?
  • BufferedImage构造函数中的类型是否应该与getScaledInstance中的类型匹配?
  • 不,TYPE 类似于 ARGB 或 RGBA,图像数据在内部存储的方式 - 选择对您的应用程序感觉最自然的方式;只需在输入 BufferedImage.[Autocomplete] 时查看您的自动完成功能即可查看所有选项
【解决方案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()

【讨论】:

    【解决方案4】:

    如果您要返回sun.awt.image.ToolkitImage,您可以将图像投射到该位置,然后使用getBufferedImage() 获取BufferedImage

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

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

    【讨论】:

    • 1) 不赞成使用 sun 包中的类。不保证它们在非 Oracle JDK 中可用。 2) 方法getBufferedImage() 仅在缓冲图像由TookitImage 内部生成时才有效。大多数情况下(99%)不是,所以返回值为nullSource Reference
    猜你喜欢
    • 2015-12-19
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    相关资源
    最近更新 更多