Skip to content

BufferedImage are Null in runtime

I’m having a problem with BufferedImage in runtime. I’m loading an .png, but the BufferedImage is null. I don’t get an IOException, but an NullPointerException. And the biggest problem to me, is that when I run this same code in netbeans he works fine…

My code is

public Image loadImage() throws IOException {
    BufferedImage bufferedImage = ImageIO.read(new File(ApplicationProperties.getPath() + "\.wimdesktop\image.png"));
    return SwingFXUtils.toFXImage(bufferedImage, null);
}

The ApplicationProperties.getPath() are static and don’t change in runtime. And if I separate the declaration of the BufferedImage and try file.exists() I get a true result

Answer

Well, read the docs. This is bizarre behaviour, sure, but the docs spell it out for you:

Returns a BufferedImage as the result of decoding a supplied File with an ImageReader chosen automatically from among those currently registered. The File is wrapped in an ImageInputStream. If no registered ImageReader claims to be able to read the resulting stream, null is returned.

(I added the highlight). It’s intentional behaviour, in other words.

This method is bad and you should never call it. Call one of the other ones, take some control back. Usually, such images are as static as your class files are: You determine what these images should be when you create this program, and your users are not meant to make them, edit them, or otherwise have any influence on it. Therefore, it makes sense to store these images in the same place you ‘store’ your class files: In a jar or jmod, together.

You can ask java to read stuff from the same place it reads class files. I think you should probably be using that mechanism instead. You need a method that takes an InputStream or URL. Fortunately, there are overloads of the read method for both. Thus:

  • If you e.g. have a java file MyApp.java, which starts with package com.foo;, then you end up having a jar file that contains the entry com/foo/MyApp.class; you can see this if you run jar tvf myapp.jar.
  • Now ensure that the image is in the same jar, either in a (subdir of) com/foo or in the root of the jar, your choice. Let’s say that you have com/foo/img/image.png inside that jar.

Then, to make a BufferedImage out of that:

BufferedImage img = ImageIO.read(MyApp.class.getResource("img/image.png"));
return SwingFXUtils.toFXImage(img, null);

If you must go off of a file for some bizarre reason, take control of the process in order to get non-idiotic error handling (The read method that takes a File, unfortunately, qualifies as idiotic error handling, so you don’t want that one):

try (FileInputStream in = new FileInputStream(new File(...))) {
   BufferedImage img = ImageIO.read(in);
}

This way, if img is now null, you know that the file was most likely read just fine, but its either not a valid image at all, or its in a format that java cannot read (for example, I don’t think java can guaranteed read anything, except png and jpg. So it might be in HEIF/HEVC, TIFF, BMP, etc – stuff java won’t be able to read as far as I know).

Contrast to what you do, where it could also be that the file does not exist or your java process does not have read access to the file.