2012-05-18 17 views
6

Ho un file con un'immagine molto grande: ad esempio 9000x9000.Decodifica una parte di Bitmap da file in Android

Impossibile caricare la bitmap in memoria perché la dimensione dell'heap. Ma ho solo bisogno di visualizzare una piccola parte di questo bitmap, ad esempio la larghezza rettificata = 100-200 e altezza = 200-400 (dimensione risultante della bitmap secondaria = 100x200)

Come posso recuperare questa bitmap dal file?

Nota: Non voglio perdere la qualità dell'immagine 100x200

Grazie

risposta

12

è possibile che ci sia una soluzione per questo?

ad esempio, BitmapRegionDecoder.

dovrebbe funzionare per API10 e soprattutto ...

+0

che sarebbe la risposta corretta. – njzk2

+0

Grazie, l'ho appena usato. Funziona. –

0

Non credo che si può. Nemmeno su un PC, non riesco a vedere come è possibile farlo senza caricare l'intera immagine: la maggior parte dei formati di immagine, ad esempio PNG, ha i dati del pixel compressi, quindi è necessario almeno decomprimere il blocco IDAT prima di poter iniziare a fare qualsiasi altra cosa e che fondamentalmente decodificherà l'intera immagine.

Nelle tue scarpe proverei a far fare un server per me. Dove prendi comunque l'immagine? Non da un server? Quindi prova a creare una richiesta WS che ti fornisca la parte corretta dell'immagine. Se l'immagine NON proviene dal server, puoi comunque inviarlo al tuo server per recuperare solo la parte dell'immagine che desideri.

+0

Grazie per la risposta. Quello che sto cercando di fare è implementare un MultiTouchImageView e questo per caricare solo la parte dell'immagine visibile a causa della posizione di zoom e scorrimento, consentendo di caricare immagini grandi senza perdere qualità e senza crash di memoria. Come lo posso fare? – Addev

+0

In questo caso, penso che ciò che stai cercando di fare sia semplicemente tecnicamente impossibile con le limitazioni di un dispositivo mobile: non puoi offrire all'utente una buona esperienza senza caricare l'intera immagine in memoria e semplicemente visualizzando la parte di cui hai bisogno . Anche se potessi caricare solo una parte dell'immagine, dovresti farlo ogni volta che l'utente esegue la panoramica o lo zoom di un bit ... poiché l'operazione sarebbe lenta, l'esperienza utente sarebbe comunque schifosa. L'unico modo per farlo è mettere un limite superiore alla dimensione dell'immagine. Altrimenti non puoi farlo IMHO. –

+0

Hmmm quello che dici è molto logico, ma come fa la Gallery di Android a caricare quelle grandi immagini permettendo di ingrandire con la stessa qualità? – Addev

2

Penso che sia possibile utilizzare il metodo BitmapFactory che consente di specificare il Rect che si desidera decodificare.

public static Bitmap decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options opts) 
+0

L'outPadding è un parametro di uscita – Addev

+0

@Addev Sono davvero interessante .. quindi non pensi che sia possibile prendere solo un po 'di bitmap prima di importarlo? :) –

+0

in quali casi viene riempito l'outPadding? quando è 9-patch? ci sono altri casi? inoltre, anche se è 9-patch, cosa significa e cosa verrebbe riempito? –

0

provare questo codice:

private Bitmap decodeFile(File f) { 
    Bitmap b = null; 
    try { 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     FileInputStream fis = new FileInputStream(f); 
     b=Bitmap.createBitmap(BitmapFactory.decodeStream(fis, null, o), 100, 200, 200, 400, null, null); 
     fis.close(); 
    } catch (IOException e) { 
    } 
    return b; 
} 

non sono sicuro, ma ciò potrebbe dare qualche idea per voi

+0

Viene visualizzato un errore di memoria insufficiente perché BitmapFactory.decodeStream (fis, null, o) non viene restituito fino a quando non viene richiamata l'intera bitmap – Addev

4

Si può facilmente essere fatto utilizzando RapidDecoder.

Ho effettivamente generato un png 9000x9000 che ha una dimensione del file di circa 80 MB e la regione di dimensioni 200x400 è stata caricata correttamente.

import rapid.decoder.BitmapDecoder; 

Bitmap bitmap = BitmapDecoder.from("big-image.png") 
          .region(145, 192, 145 + 200, 192 + 400) 
          .decode(); 
imageView.setImageBitmap(bitmap); 

Funziona per Android 2.2 e versioni successive.

+0

Wow, sembra promettente. l'intera decodifica viene eseguita su JNI? quali formati di file sono supportati? supporta anche WebP? include il rilevamento del volto? –

+0

+1 ottima libreria, anche la qualità dell'immagine è mantenuta all'80% e funziona su quasi tutti i dispositivi –

1

provare questo codice:

public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) { 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(path, options); 

     final int height = options.outHeight; 
     final int width = options.outWidth; 
     options.inPreferredConfig = Bitmap.Config.RGB_565; 
     int inSampleSize = 1; 
     if (height > reqHeight) { 
      inSampleSize = Math.round((float) height/(float) reqHeight); 
     } 
     int expectedWidth = width/inSampleSize; 
     if (expectedWidth > reqWidth) { 
      inSampleSize = Math.round((float) width/(float) reqWidth); 
     } 
     options.inSampleSize = inSampleSize; 
     options.inJustDecodeBounds = false; 
     return BitmapFactory.decodeFile(path, options); 
    } 
Problemi correlati