web-dev-qa-db-fra.com

Java obtenir l'extension / le type d'image en utilisant BufferedImage à partir de l'URL

Je connais travailler avec des images . I récupérer/lire une image à partir d'une URL , où l'URL n'a pas d'extension de fichier. Ensuite, je souhaite écrire/enregistrer l'image sur le stockage local, mais je dois spécifier l'extension du fichier image (c'est-à-dire JPG, PNG, etc.), que je ne peux pas récupérer son extension via BufferedImage.

Pourrait-on indiquer comment cela peut être fait? Toute autre méthode fera l'affaire.

27
Mr.

Utilisez ImageReader.getFormatName ()

Vous pouvez obtenir les lecteurs d'images d'un fichier en utilisant ImageIO.getImageReaders (entrée d'objet) .

Je ne l'ai pas testé moi-même, mais vous pouvez essayer ceci:

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());
}
32
Otto Allmendinger

La suggestion d'utiliser ImageIO.createImageInputStream (obj) ne fonctionnera pas si l'objet est une URL.

Une alternative consiste à utiliser la méthode URLConnection.guessContentTypeFromStream (InputStream stream). Cette méthode devine le type de contenu en examinant les 12 premiers octets d'un flux.

Une complication avec l'utilisation de cette méthode est qu'elle nécessite que le paramètre de flux donné soit marqué comme pris en charge, et le flux renvoyé par Java url.openStream () n'est pas marqué comme pris en charge.

De plus, si vous souhaitez déterminer le type de contenu et télécharger l'image sur une image tamponnée, il serait préférable que la solution ne télécharge le contenu qu'une seule fois (par opposition à deux passes, une fois pour déterminer le type de contenu et une deuxième fois pour télécharger l'image).

Une solution consiste à utiliser le PushbackInputStream. Le PushbackInputStream peut être utilisé pour télécharger les premiers octets initiaux afin de déterminer le type de contenu. Les octets peuvent ensuite être repoussés sur le flux afin que ImageIO.read (flux) puisse lire le flux dans son intégralité.

Solution possible:

// 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);
16
JohnC

Si vous obtenez l'image à partir d'une URL, cela signifie que vous pouvez accéder à l'image via un InputStream. À partir de cela, vous pouvez utiliser ImageIO pour obtenir le type d'image (format) et avec le code suivant, créez une BufferedImage en même temps.

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

  }
4
herrtim

Cela fonctionne en introduisant un objet URL (c'est-à-dire une image) et en renvoyant une extension de fichier

Cependant, il nécessite un téléchargement initial dans le répertoire Java tmp, puis il est supprimé après que ImageReader ait tenté d'obtenir la collecte du type d'image

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;



}
2
med116