Here's one way to implement background reading, and report back dimensions ASAP, and then continue reading the image in the background.
To try to answer the questions from your comments:
- You don't need to iterate over the readers. The below code doesn't, it simply tests if there's at least one reader that can read the given format, and tries reading using that. You could, if you wanted to, iterate, and try the next reader if the first failed in some way. But the logic for doing so is quite complex, and usually not needed as there's usually zero or one reader only.
- It could in theory be that one reader could read the dimensions, and fail reading the image. But again, as said above, this isn't the common case. It's usually impossible to read the image data, without knowing its dimensions.
ImageReader
instances are reusable (but not thread safe, so don't share between threads), and can be used to read many different inputs (in the same format). So this is a performance consideration in the API, I guess. You can also obtain readers based on file name, and in that case you would need to somehow pass the input anyway.
The code should be pretty self-explanatory, if you understand the code in the linked answer.
public class BackgroundImageReader implements Callable<BufferedImage> {
private final Object input;
public BackgroundImageReader(File input) {
this.input = input;
}
public BackgroundImageReader(InputStream input) {
this.input = input;
}
@Override
public BufferedImage call() throws IOException {
try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(stream);
updateImageDimensions(new Dimension(reader.getWidth(0), reader.getHeight(0)));
return reader.read(0);
} finally {
reader.dispose();
}
}
throw new IOException("Could not read image");
}
}
public void updateImageDimensions(Dimension dimension) {
// TODO: Implement callback mechanism
}
}