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.
Voici quelque chose de très simple et pratique.
BufferedImage bimg = ImageIO.read(new File(filename));
int width = bimg.getWidth();
int height = bimg.getHeight();
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.
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.
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.
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])));
}
}
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;
}
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
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
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();
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();
}
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();
}