Czy istnieje inny sposób niż użycie ImageIO.read, aby uzyskać wysokość i szerokość obrazu?
Ponieważ napotykam problem, który blokuje wątek.
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)
Ten błąd występuje tylko na serwerze aplikacji Sun i dlatego podejrzewam, że jest to błąd Sun.
java
javax.imageio
srebrny est
źródło
źródło
jstack
).Odpowiedzi:
Oto coś bardzo prostego i poręcznego.
źródło
To jest przepisanie świetnego posta autorstwa @Kay, który rzuca IOException i zapewnia wczesne wyjście:
Wydaje mi się, że moja reprezentacja nie jest wystarczająco wysoka, aby mój wkład został uznany za warty odpowiedzi.
źródło
javax.imageio.ImageIO.getImageReadersByMIMEType(mimeType)
, gdybyś chciał mieć pewność co do typu pliku?.close()
na stream przed powrotem? w przeciwnym razie zostawisz strumień otwartyorg.apache.commons.io.FilenameUtils#getExtension
do wykrywania rozszerzenia nazwy pliku.Znalazłem inny sposób odczytywania rozmiaru obrazu (bardziej ogólny). Z klasy ImageIO można korzystać we współpracy z ImageReaders. Oto przykładowy kod:
Zauważ, że getFileSuffix to metoda, która zwraca rozszerzenie ścieżki bez "." czyli np .: png, jpg itp. Przykładowa implementacja to:
To rozwiązanie jest bardzo szybkie, ponieważ z pliku odczytywany jest tylko rozmiar obrazu, a nie cały obraz. Przetestowałem to i nie ma porównania do wydajności ImageIO.read. Mam nadzieję, że komuś to się przyda.
źródło
getFileSuffix()
zawiera niepotrzebne „if”, a inicjowanie przy użyciunull
nie jest dobrym pomysłem w tym przypadku.ImageIO.read()
całkowicie z wody, zarówno pod względem czasu procesora i pamięci.Próbowałem przetestować wydajność, korzystając z różnych wymienionych podejść. Trudno jest przeprowadzić rygorystyczny test, ponieważ na wynik wpływa wiele czynników. Przygotowałem dwa foldery, jeden zawierający 330 plików jpg, a drugi 330 plików png. W obu przypadkach średni rozmiar pliku wynosił 4 MB. Następnie zadzwoniłem do getDimension dla każdego pliku. Każda implementacja metody getDimension i każdy typ obrazu były testowane osobno (osobne uruchomienie). Oto czasy wykonania, które otrzymałem (pierwsza liczba dla jpg, druga liczba dla png):
Jest oczywiste, że niektóre metody ładują cały plik w celu uzyskania wymiarów, podczas gdy inne uzyskują po prostu odczytywanie niektórych informacji nagłówka z obrazu. Myślę, że te liczby mogą być przydatne, gdy wydajność aplikacji jest krytyczna.
Dziękuję wszystkim za wkład w ten wątek - bardzo pomocny.
źródło
Możesz załadować dane binarne jpeg jako plik i samodzielnie przeanalizować nagłówki jpeg. Ten, którego szukasz, to nagłówek 0xFFC0 lub Start of Frame:
Aby uzyskać więcej informacji na temat nagłówków, sprawdź wpis JPEG na Wikipedii lub mam powyższe informacje tutaj .
Użyłem metody podobnej do poniższego kodu, który dostałem z tego posta na forach sun:
}
źródło
==192
tego warto sprawdzić numery 192-207, poza 196, 200 i 204.com.drewnoakes.metadata-extractor
biblioteki, aby łatwo wyodrębnić te nagłówkiProsta droga:
źródło
Problem z ImageIO.read polega na tym, że działa bardzo wolno. Wszystko, co musisz zrobić, to przeczytać nagłówek obrazu, aby uzyskać rozmiar.
ImageIO.getImageReader
jest idealnym kandydatem.Oto przykład Groovy, ale to samo dotyczy Javy
Wydajność była taka sama, jak przy użyciu biblioteki Java SimpleImageInfo.
https://github.com/cbeust/personal/blob/master/src/main/java/com/beust/SimpleImageInfo.java
źródło
getReaderByFormat
?Możesz użyć zestawu narzędzi, nie potrzebujesz ImageIO
Jeśli nie chcesz zajmować się ładowaniem obrazu, zrób to
źródło
Możesz uzyskać szerokość i wysokość obrazu za pomocą obiektu BufferedImage używając java.
źródło
Uzyskanie buforowanego obrazu za pomocą ImageIO.read jest bardzo ciężką metodą, ponieważ tworzy pełną nieskompresowaną kopię obrazu w pamięci. W przypadku png możesz również użyć pngj i kodu:
źródło
Po zmagał się z
ImageIO
wielu w ostatnich latach, myślę, Andrew Taylor „s rozwiązanie jest zdecydowanie najlepszym kompromisem (szybki: nie używaImageIO#read
, a uniwersalny). Dzięki!!Ale byłem trochę sfrustrowany, że zmuszono mnie do korzystania z lokalnego pliku (Plik / Ciąg), szczególnie w przypadkach, gdy chcesz sprawdzić rozmiary obrazów pochodzące, powiedzmy, z żądania wieloczęściowego / formularza-danych, z którego zwykle pobierasz
InputPart
/InputStream
. Więc szybko się wariant, który akceptujeFile
,InputStream
iRandomAccessFile
, na podstawie zdolnościImageIO#createImageInputStream
do zrobić.Oczywiście taka metoda z
Object input
, może pozostać tylko prywatna i powinieneś utworzyć tyle metod polimorficznych, ile potrzeba, nazywając tę. Można również przyjąćPath
zPath#toFile()
iURL
zURL#openStream()
przed przejściem do tej metody:źródło
Więc niestety, po wypróbowaniu wszystkich odpowiedzi z góry, nie udało mi się ich uruchomić po niestrudzonych próbach. Więc zdecydowałem się zrobić prawdziwy hack sam i robię to dla mnie. Ufam, że dla ciebie też będzie działać idealnie.
Używam tej prostej metody, aby uzyskać szerokość obrazu wygenerowanego przez aplikację, który ma zostać przesłany później do weryfikacji:
Pls. uwaga: aby uzyskać dostęp do pamięci, musisz włączyć uprawnienia w manifeście.
/ Zrobiłem to statycznie i umieściłem w mojej klasie Global, aby móc odwoływać się do niego lub uzyskiwać do niego dostęp z jednego źródła, a jeśli jest jakakolwiek modyfikacja, wszystko musiałoby być zrobione w jednym miejscu. Po prostu utrzymanie koncepcji DRY w java. (zresztą) :) /
}
źródło
Aby uzyskać rozmiar pliku emf bez EMF Image Reader, możesz użyć kodu:
źródło