2013-08-27 12 views
5

Esiste una libreria Java in grado di leggere regioni di file di immagini molto grandi (ad esempio JPEG) (> 10.000 x 10.000 pixel) senza conservare l'intera immagine in memoria.Lettura regione da file immagine molto grande in Java

In alternativa, quale libreria Java è in grado di gestire file di immagini molto grandi con un minimo di spese generali.

+0

Si desidera leggere una regione in termini di offset e lunghezza di un byte o di alcuni pixel dall'intera immagine? –

+0

Una regione in termini di pixel. – f3lix

+0

OK, prova la risposta che ho postato di seguito. –

risposta

7

Standard ImageIO consente di leggere regioni di (grandi) immagini senza prima leggere l'intera immagine in memoria.

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

Questo sembra funzionare bene. Grazie. – f3lix

+0

Ciao! Grazie per il bel codice tagliato. È effettivamente possibile scrivere una regione su un'immagine senza leggere l'intera immagine? La mia regione è a soli 100px in quadrato e mi piace conservarla in una certa posizione in un enorme Jpeg. – Durin

+0

@Durin Sì, potrebbe essere possibile in determinati formati di file. L'API ImageIO lo supporta. Ma per favore fai una nuova domanda! :-) – haraldK

0

È possibile utilizzare, ad esempio, RandomAccessFile per leggere a partire dalla metà del file: ma il problema è che l'immagine intera jpeg viene compressa dopo DCT quantizzazione (http://www.fileformat.info/mirror/egff/ch09_06.htm), quindi non credo che sia possibile leggere un frammento senza leggere l'intero file in memoria.

+1

Ho solo una conoscenza superficiale della quantizzazione JPEG e DCT, ma credo che DCT sia applicato a blocchi di 8x8 pixel e dovrebbe essere possibile evitare di decodificare tutti i blocchi per ottenere una regione. Ovviamente è necessario ottenere alcuni coefficienti/informazioni da altre parti dell'immagine, ma ciò non significa che devo leggere tutti i dati in memoria ... ma potrei sbagliarmi. – f3lix

0

È possibile utilizzare un BufferedImage per fare quello che ti serve.

// 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); 

E quindi è possibile elaborare l'immagine secondaria della regione come si desidera.

+0

... ma quello avrebbe letto l'intera cosa in memoria 1? – radai

+1

@Raman: descrivi l'approccio standard che funziona bene con le immagini di dimensioni moderate. Leggi l'immagine * whole * in BufferedImage e quindi estrai la regione. Il mio problema è che questo richiede molta memoria con immagini molto grandi, dal momento che tutti i pixel sono decodificati e conservati in memoria. Per un'immagine di dimensioni 20.000 x 30.000, ciò richiederebbe quasi 2 GB di memoria; Inoltre, il decoder passa il tempo a decodificare i pixel che non vengono mai utilizzati ... – f3lix