Gibt es eine andere Möglichkeit als ImageIO.read , um Bildhöhe und -breite zu ermitteln?
Weil ich auf ein Problem stoße, das den Thread blockiert.
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)
Dieser Fehler tritt nur auf einem Sun App-Server auf und daher vermute ich, dass es sich um einen Sun-Fehler handelt.
java
javax.imageio
Silber est
quelle
quelle
jstack
).Antworten:
Hier ist etwas sehr einfaches und handliches.
quelle
Dies ist eine Neufassung des großartigen Beitrags von @Kay, der IOException auslöst und einen frühen Exit bietet:
Ich denke, mein Repräsentant ist nicht hoch genug, um meine Eingabe als Antwort als würdig zu betrachten.
quelle
javax.imageio.ImageIO.getImageReadersByMIMEType(mimeType)
wenn Sie sich über den Dateityp sicher sein möchten ?.close()
vor Ihrer Rückkehr den Stream anrufen ? Andernfalls lassen Sie den Stream offenorg.apache.commons.io.FilenameUtils#getExtension
die Dateinamenerweiterung verwenden.Ich habe einen anderen Weg gefunden, um eine Bildgröße zu lesen (allgemeiner). Sie können die ImageIO-Klasse in Zusammenarbeit mit ImageReaders verwenden. Hier ist der Beispielcode:
Beachten Sie, dass getFileSuffix eine Methode ist, die die Erweiterung des Pfads ohne "." Zurückgibt. also zB: png, jpg usw. Beispielimplementierung ist:
Diese Lösung ist sehr schnell, da nur die Bildgröße aus der Datei und nicht das gesamte Bild gelesen wird. Ich habe es getestet und es gibt keinen Vergleich mit der Leistung von ImageIO.read. Ich hoffe, jemand wird dies nützlich finden.
quelle
getFileSuffix()
enthält unnötige ifs und das Initialisieren mitnull
ist in diesem Fall keine gute Idee.ImageIO.read()
völlig aus dem Wasser, sowohl in Bezug auf die CPU-Zeit als auch in Bezug auf die Speichernutzung.Ich habe versucht, die Leistung mit einigen der verschiedenen aufgeführten Ansätze zu testen. Es ist schwierig, einen strengen Test durchzuführen, da viele Faktoren das Ergebnis beeinflussen. Ich habe zwei Ordner vorbereitet, einen mit 330 JPG-Dateien und einen mit 330 PNG-Dateien. Die durchschnittliche Dateigröße betrug in beiden Fällen 4 MB. Dann habe ich für jede Datei getDimension aufgerufen. Jede Implementierung der getDimension-Methode und jeder Bildtyp wurde separat getestet (separater Lauf). Hier sind die Ausführungszeiten, die ich erhalten habe (erste Nummer für JPG, zweite Nummer für PNG):
Es ist offensichtlich, dass einige Methoden die gesamte Datei laden, um Dimensionen zu erhalten, während andere nur einige Header-Informationen aus dem Bild lesen. Ich denke, diese Zahlen können nützlich sein, wenn die Anwendungsleistung kritisch ist.
Vielen Dank an alle für den Beitrag zu diesem Thread - sehr hilfreich.
quelle
Sie können JPEG-Binärdaten als Datei laden und die JPEG-Header selbst analysieren. Der gesuchte ist der 0xFFC0- oder Start of Frame-Header:
Weitere Informationen zu den Headern finden Sie im JPEG-Eintrag von Wikipedia, oder ich habe die obigen Informationen hier erhalten .
Ich habe eine Methode verwendet, die dem Code ähnelt, den ich aus diesem Beitrag in den Sonnenforen erhalten habe:
}}
quelle
==192
die Nummern 192-207 überprüft werden sollten, außer 196, 200 und 204.com.drewnoakes.metadata-extractor
Bibliothek verwenden, um diese Überschriften einfach zu extrahierenEinfacher Weg:
quelle
Das Problem mit ImageIO.read ist, dass es sehr langsam ist. Sie müssen lediglich den Bildheader lesen, um die Größe zu ermitteln.
ImageIO.getImageReader
ist der perfekte Kandidat.Hier ist das Groovy-Beispiel, aber das Gleiche gilt für Java
Die Leistung war die gleiche wie bei der Verwendung der Java-Bibliothek SimpleImageInfo.
https://github.com/cbeust/personal/blob/master/src/main/java/com/beust/SimpleImageInfo.java
quelle
getReaderByFormat
?Sie können das Toolkit verwenden, ohne ImageIO zu benötigen
Wenn Sie das Laden des Bildes nicht übernehmen möchten, tun Sie dies
quelle
Sie können die Breite und Höhe des Bildes mit dem BufferedImage-Objekt mithilfe von Java ermitteln.
quelle
Das Abrufen eines gepufferten Bildes mit ImageIO.read ist eine sehr umfangreiche Methode, da eine vollständige unkomprimierte Kopie des Bilds im Speicher erstellt wird. Für PNGs können Sie auch PNGJ und den Code verwenden:
quelle
Nachdem mit gerungen
ImageIO
viel in den letzten Jahren, ich denke , Andrew Taylor ‚s Lösung bei weitem der beste Kompromiss ist (schnell: nicht mitImageIO#read
und vielseitig). Danke, Mann!!Aber ich war ein wenig gezwungen zu werden , frustriert eine lokale Datei (File / String) zu verwenden, insbesondere in Fällen , in denen Sie Bildgrößen aus Richtung überprüfen wollen, sagen wir, eine multipart / form-data Anfrage , wo Sie in der Regel abrufen
InputPart
/InputStream
s. Also habe ich schnell eine Variante gemacht, die akzeptiertFile
,InputStream
undRandomAccessFile
basierend auf der FähigkeitImageIO#createImageInputStream
, dies zu tun.Natürlich kann eine solche Methode mit
Object input
nur privat bleiben, und Sie müssen so viele polymorphe Methoden wie nötig erstellen und diese aufrufen. Sie können auchPath
mitPath#toFile()
undURL
mit akzeptieren,URL#openStream()
bevor Sie zu dieser Methode übergehen:quelle
Nachdem ich alle Antworten von oben ausprobiert hatte, brachte ich sie nach unermüdlichen Versuchen leider nicht zum Arbeiten. Also habe ich mich entschlossen, den richtigen Hack selbst zu machen und ich gehe, um für mich zu arbeiten. Ich vertraue darauf, dass es auch für Sie perfekt funktionieren würde.
Ich verwende diese einfache Methode, um die Breite eines von der App generierten Bildes zu ermitteln und es später noch zur Überprüfung hochzuladen:
Pls. Beachten Sie: Sie müssten Berechtigungen im Manifest für den Zugriffsspeicher aktivieren.
/ Ich habe es statisch gemacht und in meine globale Klasse eingefügt, damit ich von nur einer Quelle aus darauf verweisen oder darauf zugreifen kann. Wenn Änderungen vorgenommen werden, muss alles an nur einer Stelle durchgeführt werden. Nur ein DRY-Konzept in Java beibehalten. (sowieso) :) /
}}
quelle
Um die Größe der EMF-Datei ohne EMF Image Reader zu ermitteln, können Sie folgenden Code verwenden:
quelle