Trying to cast an Image to a BufferedImage

2019-09-19 10:30发布

I'm writing java code for a game and when creating the health bars I saw an exception that confused me greatly. The code and stack is below:

Code:

package com.teamanubiz.pixelhero;

import java.awt.Graphics;
import java.awt.Image;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import com.teamanubiz.gameapi.gfx.Sprite;

public class GUIRenderLayer {

  public void renderStatBar(GUIPosition pos, Graphics g, int health, int maxHealth, int mana, int maxMana) {

    Sprite healthBar = null;
    try {
        healthBar = new Sprite(ImageIO.read(new File("res\\gui\\bar.png")));
    } catch (IOException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
    healthBar.crop(0, 0, 128, 32);
    healthBar.scale(256, 32);
    Sprite manaBar = null;
    try {
        manaBar = new Sprite(ImageIO.read(new File("res\\gui\\bar.png")));
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    manaBar.crop(0, 32, 128, 32);
    manaBar.scale(265, 16);
    Sprite temp = null;
    try {
        temp = new Sprite(ImageIO.read(new File("res\\gui\\bar.png")));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    temp.crop(0, 64, 128, 32);
    temp.scale(256, 32);
    Sprite emptyHealth = new Sprite(temp.getCurrent());
    temp.scale(256, 16);
    Sprite emptyMana = new Sprite(temp.getCurrent());

    if (pos == GUIPosition.BOTTOM) {

      double percent_h = health / maxHealth;
      double percent_m = mana / maxMana;

      healthBar.crop(0, 0, (int) ((int) 256 * percent_h), 32);
      manaBar.crop(0, 0, (int) ((int) 256 * percent_m), 16);

      g.drawImage(emptyMana.getCurrent(), 100, 464, null);
      g.drawImage(emptyHealth.getCurrent(), 100, 432, null);
      g.drawImage(healthBar.getCurrent(), 100, 432, null);
      g.drawImage(manaBar.getCurrent(), 100, 464, null);

    }

  }

}

This class is referencing a custom library containing the class Sprite. It for some reason says that I am trying to cast a ToolkitImage to a BufferedImage in the below method of Sprite.java.

public void crop(int xOffset, int yOffset, int width, int height) {

    BufferedImage temp = (BufferedImage) source;

    temp = temp.getSubimage(xOffset, yOffset, width, height);

    source = temp;

}

The variable source is an instance of an Image that is a field in Sprite.java

The stack below claims I am creating a ToolkitImage despite the fact new ImageIcon("res\\gui\\bar.png").getImage() returns only an Image. I do not convert the Image to a ToolkitImage ever in the code. This makes it extremely confusing.

Stacktrace:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage
    at com.teamanubiz.gameapi.gfx.Sprite.crop(Sprite.java:48)
    at com.teamanubiz.pixelhero.GUIRenderLayer.renderStatBar(GUIRenderLayer.java:55)
    at com.teamanubiz.pixelhero.GameWindow.tick(GameWindow.java:14)
    at com.teamanubiz.gameapi.Display.paint(Display.java:95)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1300(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage
    at com.teamanubiz.gameapi.gfx.Sprite.crop(Sprite.java:48)
    at com.teamanubiz.pixelhero.GUIRenderLayer.renderStatBar(GUIRenderLayer.java:55)
    at com.teamanubiz.pixelhero.GameWindow.tick(GameWindow.java:14)
    at com.teamanubiz.gameapi.Display.paint(Display.java:95)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1300(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage
    at com.teamanubiz.gameapi.gfx.Sprite.crop(Sprite.java:48)
    at com.teamanubiz.pixelhero.GUIRenderLayer.renderStatBar(GUIRenderLayer.java:55)
    at com.teamanubiz.pixelhero.GameWindow.tick(GameWindow.java:14)
    at com.teamanubiz.gameapi.Display.paint(Display.java:95)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1300(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

2条回答
虎瘦雄心在
2楼-- · 2019-09-19 10:42

No you don't "convert" the Image to a ToolKitImage, but that's what the JVM is giving you when you call new ImageIcon("res\\gui\\bar.png").getImage(), and not a BufferedImage. The ImageIcon API states that getImage() returns an object of Image type, but does not specify what type of Image. Since Image is an interface, you know that there must be some concrete type underlying the returned Image object. If you need a BufferedImage you could one, and draw this Image into it.

Myself, I wouldn't even use an ImageIcon here if I wanted a BufferedImage, but rather would use ImageIO.read(...) which returns a BufferedImage.

So....

BufferedImage img = ImageIO.read(getClass().getResourceAsStream("res/gui/bar.png"));
Sprite healthBar  = new Sprite(img);
查看更多
Bombasti
3楼-- · 2019-09-19 10:49

BufferedImage is a type of Image, but Image is not a type BufferedImage, you could, for example, cast BufferedImage to an Image.

Instead of using ImageIcon to load the image, use ImageIO.read, which returns a BufferedImage

So instead of...

 Sprite healthBar = new Sprite((Image)new ImageIcon("res\\gui\\bar.png").getImage()); // I Never Instatiated a ToolkitImage!!!!!!!!

Nb: ImageIcon delegates the actual loading of the image to Toolkit and wraps it in a Icon interface

Use something like...

Sprite healthBar = new Sprite(ImageIO.read(new File("res\\gui\\bar.png")));
查看更多
登录 后发表回答