Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java get image extension/type using BufferedImage from URL

Tags:

java

image

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.

like image 745
Mr. Avatar asked Jul 12 '12 07:07

Mr.


4 Answers

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()); } 
like image 141
Otto Allmendinger Avatar answered Sep 22 '22 17:09

Otto Allmendinger


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); 
like image 22
JohnC Avatar answered Sep 22 '22 17:09

JohnC


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;
    }

  }
like image 28
herrtim Avatar answered Sep 22 '22 17:09

herrtim


This works by feeding in a URL object (that is an image), and returning a file extension

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;



}
like image 24
med116 Avatar answered Sep 20 '22 17:09

med116