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
Advertisement
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 withpackage com.foo;
, then you end up having a jar file that contains the entrycom/foo/MyApp.class
; you can see this if you runjar 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 havecom/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.