Mark Doe
Mark Doe

Reputation: 125

How to solve java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0?

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:

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

Answers (3)

Lauryn Jefferson
Lauryn Jefferson

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

Harald K
Harald K

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

JojOatXGME
JojOatXGME

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:

First solution

One solution would be to load the image with blocking IO. Just like descripted in the answers of the linked question.

Second solution

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

Related Questions