I am familiar with working with images. I retrieve/read an image from a URL, where the URL does not have a file extension. Then I wish to write/save the image to the local storage, but I have to specify the image file extension (i.e. JPG, PNG, etc.), which I cannot retrieve its extension through the BufferedImage.
Could one please point out how it can be done? Any other method will do.
Use ImageReader.getFormatName()
You can get the image readers for a file using ImageIO.getImageReaders(Object input).
I haven't tested it myself, but you can try this:
ImageInputStream iis = ImageIO.createImageInputStream(file); Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(iis); while (imageReaders.hasNext()) { ImageReader reader = (ImageReader) imageReaders.next(); System.out.printf("formatName: %s%n", reader.getFormatName()); }
The suggestion to use ImageIO.createImageInputStream(obj) will not work if the object is a URL.
One alternative is to use the URLConnection.guessContentTypeFromStream(InputStream stream) method. This method guesses the content type by examining the first 12 bytes of a stream.
One complication with using this method is that it requires the given stream parameter to be mark supported, and the stream returned by java url.openStream() is not mark supported.
Additionally, if you want to be determine the content type and download the image to a BufferedImage, then it would be preferable if the solution only downloaded the content once (as opposed to making two passes, once to determine the content type and a second time to download the image).
One solution is to use the PushbackInputStream. The PushbackInputStream can be used to download the first initial bytes to determine content type. The bytes can then be pushed back on the stream so that the ImageIO.read(stream) can read the stream in its entirety.
Possible solution:
// URLConnection.guessContentTypeFromStream only needs the first 12 bytes, but // just to be safe from future java api enhancements, we'll use a larger number int pushbackLimit = 100; InputStream urlStream = url.openStream(); PushbackInputStream pushUrlStream = new PushbackInputStream(urlStream, pushbackLimit); byte [] firstBytes = new byte[pushbackLimit]; // download the first initial bytes into a byte array, which we will later pass to // URLConnection.guessContentTypeFromStream pushUrlStream.read(firstBytes); // push the bytes back onto the PushbackInputStream so that the stream can be read // by ImageIO reader in its entirety pushUrlStream.unread(firstBytes); String imageType = null; // Pass the initial bytes to URLConnection.guessContentTypeFromStream in the form of a // ByteArrayInputStream, which is mark supported. ByteArrayInputStream bais = new ByteArrayInputStream(firstBytes); String mimeType = URLConnection.guessContentTypeFromStream(bais); if (mimeType.startsWith("image/")) imageType = mimeType.substring("image/".length()); // else handle failure here // read in image BufferedImage inputImage = ImageIO.read(pushUrlStream);
If you get the image from a URL, that means you can access the image through an InputStream
. From that you can use ImageIO
to get the image type (format) and with the following code, create a BufferedImage at the same time.
public static BufferedImageWrapper getImageAndTypeFromInputStream(InputStream is) {
String format = null;
BufferedImage bufferedimage = null;
try (ImageInputStream iis = ImageIO.createImageInputStream(is);) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
if (readers.hasNext()) {
ImageReader reader = readers.next();
format = reader.getFormatName();
reader.setInput(iis);
bufferedimage = reader.read(0);
}
} catch (IOException e) {
logger.error("ERROR DETERMINING IMAGE TYPE!!!", e);
}
return new BufferedImageWrapper(format, bufferedimage);
}
public static class BufferedImageWrapper {
private final String imageType;
private final BufferedImage bufferedimage;
/**
* Constructor
*
* @param imageType
* @param bufferedimage
*/
public BufferedImageWrapper(String imageType, BufferedImage bufferedimage) {
this.imageType = imageType;
this.bufferedimage = bufferedimage;
}
public String getImageType() {
return imageType;
}
public BufferedImage getBufferedimage() {
return bufferedimage;
}
}
It requires an initial download though, to the java tmp directory, and it is then deleted after the ImageReader attempts to get the gather the image type
public String getImageFileExtFromUrl(URL urlObject) throws URISyntaxException, IOException{
System.out.println("IN DOWNLOAD FILE FROM URL METHOD");
String tmpFolder = System.getProperty("java.io.tmpdir");
String tmpFileStr = tmpFolder + "/" + new Date().getTime();
Files.copy(urlObject.openStream(), Paths.get(tmpFileStr), StandardCopyOption.REPLACE_EXISTING);
File download = new File(tmpFileStr);
System.out.println("FILE DOWNLOAD EXISTS: " + download.exists() );
try{
ImageInputStream iis = ImageIO.createImageInputStream(download);
Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
ImageReader reader = iter.next();
String formatName = reader.getFormatName();
System.out.println("FOUND IMAGE FORMAT :" + formatName);
iis.close();
return formatName;
}catch(Exception e){
e.printStackTrace();
}finally{
Files.delete(Paths.get(tmpFileStr));
}
return null;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With