web-dev-qa-db-fra.com

Comment obtenir la hauteur et la largeur de l'image en utilisant java?

Existe-t-il un autre moyen que d'utiliser ImageIO.read pour obtenir la hauteur et la largeur de l'image?

Parce que je rencontre un problème qui bloque le fil.

at com.Sun.medialib.codec.jpeg.Decoder.njpeg_decode(Native Method)      
at com.Sun.medialib.codec.jpeg.Decoder.decode(Decoder.Java:87)      
at com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader.decode(CLibJPEGImageReader.Java:73)     
 - locked <0xd96fb668> (a com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader)      
at com.Sun.media.imageioimpl.plugins.clib.CLibImageReader.getImage(CLibImageReader.Java:320)    
 - locked <0xd96fb668> (a com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader)     
 at com.Sun.media.imageioimpl.plugins.clib.CLibImageReader.read(CLibImageReader.Java:384)   
 - locked <0xd96fb668> (a com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader)      
at javax.imageio.ImageIO.read(ImageIO.Java:1400)      
at javax.imageio.ImageIO.read(ImageIO.Java:1322)

Cette erreur ne se produit que sur un serveur d'applications Sun. Par conséquent, je soupçonne qu'il s'agit d'un bogue Sun.

93
Dick Song

Voici quelque chose de très simple et pratique.

BufferedImage bimg = ImageIO.read(new File(filename));
int width          = bimg.getWidth();
int height         = bimg.getHeight();
264
Apurv

Ceci est une réécriture de l'excellent message de @Kay, qui lève IOException et fournit une sortie anticipée:

/**
 * Gets image dimensions for given file 
 * @param imgFile image file
 * @return dimensions of image
 * @throws IOException if the file is not a known image
 */
public static Dimension getImageDimension(File imgFile) throws IOException {
  int pos = imgFile.getName().lastIndexOf(".");
  if (pos == -1)
    throw new IOException("No extension for file: " + imgFile.getAbsolutePath());
  String suffix = imgFile.getName().substring(pos + 1);
  Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffix);
  while(iter.hasNext()) {
    ImageReader reader = iter.next();
    try {
      ImageInputStream stream = new FileImageInputStream(imgFile);
      reader.setInput(stream);
      int width = reader.getWidth(reader.getMinIndex());
      int height = reader.getHeight(reader.getMinIndex());
      return new Dimension(width, height);
    } catch (IOException e) {
      log.warn("Error reading: " + imgFile.getAbsolutePath(), e);
    } finally {
      reader.dispose();
    }
  }

  throw new IOException("Not a known image file: " + imgFile.getAbsolutePath());
}

Je suppose que mon représentant n'est pas assez élevé pour que mes contributions soient considérées comme dignes de réponse.

59
Andrew Taylor

J'ai trouvé un autre moyen de lire une taille d'image (plus générique). Vous pouvez utiliser la classe ImageIO en coopération avec ImageReaders. Voici l exemple de code:

private Dimension getImageDim(final String path) {
    Dimension result = null;
    String suffix = this.getFileSuffix(path);
    Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffix);
    if (iter.hasNext()) {
        ImageReader reader = iter.next();
        try {
            ImageInputStream stream = new FileImageInputStream(new File(path));
            reader.setInput(stream);
            int width = reader.getWidth(reader.getMinIndex());
            int height = reader.getHeight(reader.getMinIndex());
            result = new Dimension(width, height);
        } catch (IOException e) {
            log(e.getMessage());
        } finally {
            reader.dispose();
        }
    } else {
        log("No reader found for given format: " + suffix));
    }
    return result;
}

Notez que getFileSuffix est une méthode qui renvoie l'extension du chemin sans "." Ainsi, par exemple: png, jpg, etc. Exemple de mise en œuvre:

private String getFileSuffix(final String path) {
    String result = null;
    if (path != null) {
        result = "";
        if (path.lastIndexOf('.') != -1) {
            result = path.substring(path.lastIndexOf('.'));
            if (result.startsWith(".")) {
                result = result.substring(1);
            }
        }
    }
    return result;
}

Cette solution est très rapide car seule la taille de l’image est lue à partir du fichier et non l’ensemble de l’image. Je l'ai testé et il n'y a aucune comparaison avec les performances d'ImageIO.read. J'espère que quelqu'un trouvera cela utile.

44
user350756

J'ai essayé de tester les performances en utilisant certaines des différentes approches énumérées. Il est difficile de faire un test rigoureux car de nombreux facteurs influent sur le résultat. J'ai préparé deux dossiers, l'un contenant 330 fichiers jpg et l'autre contenant 330 fichiers png. La taille moyenne des fichiers était de 4 Mo dans les deux cas. Ensuite, j'ai appelé getDimension pour chaque fichier. Chaque implémentation de la méthode getDimension et chaque type d'image ont été testés séparément (exécution séparée). Voici les temps d'exécution que j'ai obtenus (premier numéro pour jpg, deuxième numéro pour png):

1(Apurv) - 101454ms, 84611ms
2(joinJpegs) - 471ms, N/A
3(Andrew Taylor) - 707ms, 68ms
4(Karussell, ImageIcon) - 106655ms, 100898ms
5(user350756) - 2649ms, 68ms

Il est évident que certaines méthodes chargent l'intégralité du fichier pour obtenir les dimensions, tandis que d'autres se contentent de lire certaines informations d'en-tête de l'image. Je pense que ces chiffres peuvent être utiles lorsque les performances des applications sont essentielles.

Merci à tous pour votre contribution à ce fil - très utile.

40
mp31415

Vous pouvez charger des données binaires jpeg sous forme de fichier et analyser vous-même les en-têtes jpeg. Celui que vous recherchez est l'en-tête 0xFFC0 ou Start of Frame:

Start of frame marker (FFC0)

* the first two bytes, the length, after the marker indicate the number of bytes, including the two length bytes, that this header contains
* P -- one byte: sample precision in bits (usually 8, for baseline JPEG)
* Y -- two bytes
* X -- two bytes
* Nf -- one byte: the number of components in the image
      o 3 for color baseline JPEG images
      o 1 for grayscale baseline JPEG images

* Nf times:
      o Component ID -- one byte
      o H and V sampling factors -- one byte: H is first four bits and V is second four bits
      o Quantization table number-- one byte

The H and V sampling factors dictate the final size of the component they are associated with. For instance, the color space defaults to YCbCr and the H and V sampling factors for each component, Y, Cb, and Cr, default to 2, 1, and 1, respectively (2 for both H and V of the Y component, etc.) in the Jpeg-6a library by the Independent Jpeg Group. While this does mean that the Y component will be twice the size of the other two components--giving it a higher resolution, the lower resolution components are quartered in size during compression in order to achieve this difference. Thus, the Cb and Cr components must be quadrupled in size during decompression.

Pour plus d'informations sur les en-têtes, consultez l'entrée jpeg de wikipedia ou j'ai les informations ci-dessus ici .

J'ai utilisé une méthode similaire au code ci-dessous dont je viens de cet article sur les forums Sun:

import Java.awt.Dimension;
import Java.io.*;

public class JPEGDim {

public static Dimension getJPEGDimension(File f) throws IOException {
    FileInputStream fis = new FileInputStream(f);

    // check for SOI marker
    if (fis.read() != 255 || fis.read() != 216)
        throw new RuntimeException("SOI (Start Of Image) marker 0xff 0xd8 missing");

    Dimension d = null;

    while (fis.read() == 255) {
        int marker = fis.read();
        int len = fis.read() << 8 | fis.read();

        if (marker == 192) {
            fis.skip(1);

            int height = fis.read() << 8 | fis.read();
            int width = fis.read() << 8 | fis.read();

            d = new Dimension(width, height);
            break;
        }

        fis.skip(len - 2);
    }

    fis.close();

    return d;
}

public static void main(String[] args) throws IOException {
    System.out.println(getJPEGDimension(new File(args[0])));
}

}

13
joinJpegs

Manière simple:

BufferedImage readImage = null;

try {
    readImage = ImageIO.read(new File(your path);
    int h = readImage.getHeight();
    int w = readImage.getWidth();
} catch (Exception e) {
    readImage = null;
}
9
user1215499

Le problème avec ImageIO.read, c'est qu'il est vraiment lent. Tout ce que vous avez à faire est de lire l'en-tête de l'image pour obtenir la taille. ImageIO.getImageReader est le candidat idéal.

Voici l'exemple de Groovy, mais la même chose s'applique à Java

def stream = ImageIO.createImageInputStream(newByteArrayInputStream(inputStream))
def formatReader = ImageIO.getImageWritersByFormatName(format).next() 
def reader = ImageIO.getImageReader(formatReader)
reader.setInput(stream, true)

println "width:reader.getWidth(0) -> height: reader.getHeight(0)"

La performance était la même que si vous utilisiez SimpleImageInfo Java bibliothèque.

https://github.com/cbeust/personal/blob/master/src/main/Java/com/beust/SimpleImageInfo.Java

4
argoden

Essayez d'utiliser la classe ImageInfo disponible gratuitement, je l'ai utilisée dans le même but:

http://linux.softpedia.com/get/Multimedia/Graphics/ImageInfo-19792.shtml

4
karim79

Vous pouvez utiliser la boîte à outils, pas besoin d’ImageIO

Image image = Toolkit.getDefaultToolkit().getImage(file.getAbsolutePath());
int width = image.getWidth(null);
int height = image.getHeight(null);

Si vous ne voulez pas gérer le chargement de l'image, faites

ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath());
int height = imageIcon.getIconHeight();
int width = imageIcon.getIconWidth();
3
Karussell

Obtenir une image en mémoire tampon avec ImageIO.read est une méthode très lourde, car elle crée une copie complète non compressée de l'image en mémoire. Pour png, vous pouvez aussi utiliser pngj et le code:

if (png)
    PngReader pngr = new PngReader(file);
    width = pngr.imgInfo.cols;
    height = pngr.imgInfo.rows;
    pngr.close();
}
1
Jessi

Vous pouvez obtenir la largeur et la hauteur de l'image avec l'objet BufferedImage en utilisant Java.

public void setWidthAndHeightImage(FileUploadEvent event){
    byte[] imageTest = event.getFile().getContents();
                baiStream = new ByteArrayInputStream(imageTest );
                BufferedImage bi = ImageIO.read(baiStream);
                //get width and height of image
                int imageWidth = bi.getWidth();
                int imageHeight = bi.getHeight();
    }
1
KIBOU Hassan