2

I want to read Images (.png files) in my project, and I want this to work in a runnable .jar file too. So I wrote this little piece of code:

try {
    InputStream in;
    in = Loader.class.getClassLoader().getResourceAsStream("buttons.png");

    System.out.println(in.read() + ", Reader: " + in);          

    BufferedImage img = ImageIO.read(in);

    System.out.println(img.getHeight());

    in.close(); 
} catch (IOException e) {
    e.printStackTrace();
}

When I run it, I get the following output:

137, Reader: java.io.BufferedInputStream@15db9742
Exception in thread "main" java.lang.NullPointerException
    at test.Loader.load(Loader.java:21)
    at test.MainTest.main(MainTest.java:6)

My MainTest does nothing but running this code, so I won't include it here.

I already tested if the InputStream is null as you may have noticed. As it obviously isn't the path to my file has to be right. My question is: Why is ImageIO.read() returning null?

2
  • Check that buttons.png is at the root directory of the class path of Loader. Case-sensitive, Inspect the .jar file with 7zip, WinZip or the like. Commented Feb 16, 2016 at 19:07
  • 1
    getResource(AsStream) will return null when the resource can't be found Commented Feb 16, 2016 at 20:49

3 Answers 3

4

The problem with your code is the line that reads from in before passing it to ImageIO.read(..) (you are reading the first byte):

System.out.println(in.read() + ", Reader: " + in);

When you read a byte from the stream, this byte is effectively "consumed" and will not be read again, thus ImageIO will never see this byte, causing the file format (PNG) to not be recognized. In this case, ImageIO.read(..) will return null.

Just remove that line, and your code should work fine.

The file seems to be present as in is not null. And the value 137 that you print, is actually the first byte of the PNG signature, meaning the file is fine and properly included in your JAR.


If you really need to peek into the bytes in the stream before passing to ImageIO, you could do something like:

in.mark(256); // allows you to read up to 256 bytes before calling reset()
System.out.println(in.read() + ", Reader: " + in); // or whatever you like to do
in.reset(); // "rewind" to beginning of stream (previous mark)

Just be careful, as not all streams supports mark()/reset() methods (you can test, using the boolean markSupported() method).

Sign up to request clarification or add additional context in comments.

1 Comment

Youre absolutely right. I worked that one out now too :D. But thank you very much for your help and the detailed explanation :)
1

As you already read on the InputStream before the call to ImageIO.read, it may happens that the function is unable to decode the image correctly. Remove the call to in.read(), and test the results of the calls.

Comments

0

https://docs.oracle.com/javase/8/docs/api/javax/imageio/ImageIO.html#read-javax.imageio.stream.ImageInputStream-

ImageIO.read(...) may return null if it's unable to decode the image. Check for that case as well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.