Reputation: 125
I've been spending the last hours trying to solve the stack trace below. With major research on here SO and also through Google, I understand the exception can mean several things:
the program can't find the requested images with the provided path;
the images are being rendered after the width and the height are generated, reason why it equals 0...
Am I missing something? I can't figure out how to solve this...
Stack
Exception in thread "main" java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0 at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016) at java.awt.image.BufferedImage.(BufferedImage.java:331) at tp6.Interface.toBufferedImage(Interface.java:157) at tp6.Interface.(Interface.java:36) at tp6.Interface.main(Interface.java:171)
tp6.Interface.toBufferedImage(Interface.java:157):
public BufferedImage toBufferedImage(Image image) {
if( image instanceof BufferedImage ) {
return( (BufferedImage)image );
} else {
image = new ImageIcon(image).getImage();
BufferedImage bufferedImage = new BufferedImage(
image.getWidth(null),
image.getHeight(null),
BufferedImage.TYPE_INT_RGB );
Graphics g = bufferedImage.createGraphics();
g.drawImage(image,0,0,null);
g.dispose();
return( bufferedImage );
}
}
tp6.Interface.(Interface.java:36)
//IMAGE JPANEL
Image map=new ImageIcon("images/main.gif").getImage();
Image digi=new ImageIcon("images/digits.gif").getImage();
BufferedImage mapmodifiable= toBufferedImage(map);
BufferedImage digits= toBufferedImage(digi);
tp6.Interface.main(Interface.java:171)
public static void main(String[] args)
{
Window windowintro = new Window( 440, 400, 1);
//INTERFACE GRAPHIC
Interface graphic=new Interface();
graphic.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
}
Upvotes: 4
Views: 13218
Reputation: 13
I was having this problem too. I solved it by adding one line of code. In your in the first line of your toBufferedImage() method you can put
while(image.getWidth() == -1);
This line will just keep looping until there is a value in getWidth() besides -1.
Upvotes: 1
Reputation: 27084
The reason for the exception has already been explained, Image
methods getWidth(null)
and getHeight(null)
both return -1
when the image dimensions are not (yet) known. This is implemented so, because the old Image
API in Java is asynchronous and loads image resources off the current thread. As you write, it could also happen because the image is not found.
However, as you want to use your images as BufferedImage
s (presumably because you want to modify them at some stage), it's better and easier to just load them using the more recent synchronous ImageIO
API. In most cases, the code will be clearer and easier to understand, and more importantly; you'll get error messages right away if the image can't be found/loaded.
So, instead of:
Image map = new ImageIcon("images/main.gif").getImage();
BufferedImage mapmodifiable = toBufferedImage(map);
You can simply do:
BufferedImage mapmodifiable = ImageIO.read(new File("images/main.gif"));
PS: It is possible to convert an Image
to a BufferedImage
like you do in your toBufferedImage
method, and using ImageIcon.getImage(..)
should ensure the image was preloaded (ImageIcon
internally uses a MediaTracker
for preloading). However, as I say above, the old Image
API is not very good at error feedback, so most likely the problem is that your image isn't found.
Upvotes: 3
Reputation: 3296
I found this question concerning your problem. Maybe you are using an asynchronous way to load the images. This mean the image may not be loaded yet, when you are calling getWidth(null)
or getHeight(null)
. Since the image may not be loaded at this time, the width and height may not be known yet. This is the reason why -1
is returned.
Maybe you will get the right result if you add some delay with Thread.sleep(1000)
. I did not investigate it but it is definitively not a good solution. You may sleep not long enough on some systems. On other systems you may sleep unnecessary long. And since I do not know the specification very well, it may even be a valid implementation of Java if Thread.sleep
blocks the process from reading the image (Does someone know it?).
I would see two ways which could be used to solve the problem:
One solution would be to load the image with blocking IO. Just like descripted in the answers of the linked question.
Another solution would be to use an ImageObserver:
int width = getWidth(new ImageObserver() {
@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
// TODO use the width when the image is loaded and the size is known
}
});
if (width != -1) {
// TODO use the width, it is already known
}
Upvotes: 0