'When calling javax.imageio.ImageIO.read, can I specify the format?

In Java, I want to use the class javax.imageio.ImageIO to read a image from an InputStream. This class has a static method, read(InputStream input), which can do this.

However, this method does not allow me to specify the format (such as png, jpeg, bmp ...). According to the documentation of this class, it seems that this method will detect the format automatically from the InputStream. But to me, this seems unsafe. What if a byte sequence can be interpreted as two different image formats? After all, a byte sequence is meaningless unless a format is specified. Besides, it seems that custom image formats and their readers can be registered to the ImageIO class, which makes this problem more severe.

So, is there a way to read an image from an InputStream with a format specified?



Solution 1:[1]

No, none of the static ImageIO.read(...) methods allows specifying the format to be read.

For these methods, the registered reader plugins briefly inspects the stream/file contents and decides whether or not it is able to decode it. The first reader plugin that can decode is chosen, and an actual reader instance is created to perform the decoding.

For most file formats, this method is a common and completely safe way to determine the file format, and is based on the "magic identifier" or file signature. There are file formats that does not have such signatures that are hard to detect, like WBMP, PICT or old TGA files. But the formats you mention, like BMP, JPEG and PNG are all easily and correctly detected using this mechanism.


If however, you know that your inputs are always the same format or explicitly only want to support a single format, that is possible with a little extra code. This is probably also a tiny bit faster than detecting the file format by inspection, although I doubt it matters much.

If the only format you want is JPEG, use ImageIO.getImageReadersByFormatName("JPEG") (getImageReadersBySuffix("jpg") or getImageReadersByMIMEType("image/jpeg") will also do) to get a reader and then pass the input directly to this reader. The code would look something like this:

Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
ImageReader reader = readers.next(); // There should always be a JPEG reader installed, for other formats you might want to check

try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
    reader.setInput(stream);
    BufferedImage image = reader.read(0);
}
finally {
    reader.dispose();
}

Solution 2:[2]

Yes you can speficy the format. You do that with the file name.

BufferedImage img = ImageIO.read(new File("abc.jpg"));

For more information, like accepted file formats, take a look here. https://docs.oracle.com/javase/tutorial/2d/images/loadimage.html

Solution 3:[3]

This topic didn't let me sleep last night. Take a look at this solution:

The computer must know, how to handle a file and for that, it takes a look into the file. Just open an image with the normal editor and you see what I mean.

You can write a method for specification by yourself. This method needs to read a file (or a part of it), and then check for the format.

filesOpenedWithEditor

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 David Weber
Solution 3 David Weber