0

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)
Galen Nare
  • 376
  • 2
  • 4
  • 18

2 Answers2

2

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);
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
2

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")));
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I just did that and the Exception changed. `at com.teamanubiz.pixelhero.GUIRenderLayer.renderStatBar(GUIRenderLayer.java:55)` now it is inside the **if** statement in GUIRenderLayer at the first `crop()` reference. – Galen Nare Nov 11 '14 at 20:30
  • I have also thought out that the Images could be converted by the Java API when I'm using `Image.getScaledInstance(int,int)` in `Sprite.scale(int,int)`. – Galen Nare Nov 11 '14 at 20:38
  • "I have also thought out that the Images could be converted by the Java API when I'm using Image.getScaledInstance(int,int) in Sprite.scale(int,int)." I have found this is true, but I have no idea how to work around it. I don't have any choice but to scale the image. – Galen Nare Nov 11 '14 at 21:40
  • You can scale a `BufferedImage` using a verity of techniques, the preferred is usually to use the `Graphics2D` API, for [example](http://stackoverflow.com/questions/11959758/java-maintaining-aspect-ratio-of-jpanel-background-image/11959928#11959928) and [example](http://stackoverflow.com/questions/14115950/quality-of-image-after-resize-very-low-java/14116752#14116752). You should also have a look at [The Perils of Image.getScaledInstance()](https://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html) – MadProgrammer Nov 11 '14 at 22:13
  • I have no idea how I fixed it. I changed Sprite.java to make the scaled image a `BufferedImage`, and then the Sprite didn't scale, so then I rolled back my library that Sprite was being used in, and for some odd reason, it suddenly worked without a problem. I'm stumped. Thanks for your help, though! `ImageIO.read()` works like a charm. I looked at the page you sent me. I had no idea you could scale the image right as it's rendering. You learn something new every day... – Galen Nare Nov 11 '14 at 22:15