2013-08-27 16 views
5

Czy istnieje biblioteka Java, która może odczytać obszary o bardzo dużych plikach graficznych (na przykład JPEG) (> 10 000 x 10 000 pikseli) bez zachowywania całego obrazu w pamięci.Odczytywanie regionu z bardzo dużego pliku obrazu w Javie

Lub alternatywnie, która biblioteka Java może obsługiwać bardzo duże pliki obrazów z minimalnym narzutem.

+0

Czy chcesz odczytać region pod względem przesunięcia bajtu i długości lub kilku pikseli od całego obrazu? –

+0

Region pod względem pikseli. – f3lix

+0

Dobrze, wypróbuj odpowiedź, którą zamieściłem poniżej. –

Odpowiedz

7

Standardowy ImageIO pozwala na odczyt regionów (dużych) obrazów bez uprzedniego odczytu całego obrazu do pamięci.

Rectangle sourceRegion = new Rectangle(x, y, w, h); // The region you want to extract 

ImageInputStream stream = ImageIO.createImageInputStream(input); // File or input stream 
Iterator<ImageReader> readers = ImageIO.getImageReaders(stream); 

if (readers.hasNext()) { 
    ImageReader reader = readers.next(); 
    reader.setInput(stream); 

    ImageReadParam param = reader.getDefaultReadParam(); 
    param.setSourceRegion(sourceRegion); // Set region 

    BufferedImage image = reader.read(0, param); // Will read only the region specified 
} 
+0

To wydaje się działać dobrze. Dzięki. – f3lix

+0

Cześć! Dzięki za ten bardzo ładny kod snipped. Czy możliwe jest zapisanie regionu do obrazu bez czytania całego obrazu? Mój region ma tylko 100 pikseli w kwadracie i lubię go przechowywać w określonej lokalizacji w ogromnym Jpeg. – Durin

+0

@Durin Tak, może to być możliwe w niektórych formatach plików. Obsługuje go interfejs Imageio API. Ale proszę zadać nowe pytanie! :-) – haraldK

0

można użyć, na przykład, RandomAccessFile czytać od połowy pliku: ale problem jest to, że cały JPEG są kompresowane po DCT kwantyzacji (http://www.fileformat.info/mirror/egff/ch09_06.htm), więc nie sądzę, że jest to możliwe przeczytać fragment bez czytania całego pliku do pamięci.

+1

Mam tylko powierzchowną wiedzę na temat kwantyzacji JPEG i DCT, ale uważam, że DCT stosuje się do bloków 8x8 pikseli i powinno być możliwe uniknięcie dekodowania wszystkich bloków w celu uzyskania regionu. Oczywiście konieczne jest uzyskanie pewnych współczynników/informacji z innych części obrazu, ale to nie znaczy, że muszę czytać wszystkie dane w pamięci ... ale mogę się mylić. – f3lix

0

Możesz użyć BufferedImage, aby zrobić to, czego potrzebujesz.

// Set these variables according to your requirements 
int regionX, regionY, regionWidth, regionHeight;  

BufferedImage image = ImageIO.read(new File("/path/to/image.jpg")); 
BufferedImage region = image.getSubimage(regionX, regionY, regionWidth, regionHeight); 

A następnie można obrabiać subimage regionu, jak chcesz.

+0

... ale to odczytałoby całość w pamięci 1? – radai

+1

@Raman: opisujesz standardowe podejście, które działa dobrze w przypadku zdjęć o umiarkowanej wielkości. Czytasz obraz * cały * w BufferedImage, a następnie wyodrębniasz region. Mój problem polega na tym, że wymaga to dużej ilości pamięci z bardzo dużymi obrazami, ponieważ wszystkie piksele są dekodowane i przechowywane w pamięci. Dla obrazu o rozmiarze 20 000 x 30 000, wymagałoby to prawie 2 GB pamięci; plus, dekoder poświęca czas na dekodowanie pikseli, które nigdy nie są używane ... – f3lix

Powiązane problemy