2013-10-30 15 views
15

Devo inviare un'immagine da un file a un server. Il server richiede l'immagine con una risoluzione di 2400x2400.BitmapFactory.decode. Memoria insufficiente con immagini 2400x2400

Quello che sto cercando di fare è:

1) Ottenere un bitmap utilizzando BitmapFactory.decodeFile utilizzando l'inSampleSize corretta.

2) comprime l'immagine in formato JPEG con una qualità del 40%

3) Codificare l'immagine in base64

4) inviata al server

non riesco a raggiungere il primo passo, lancia un'eccezione di memoria insufficiente. Sono sicuro che inSampleSize sia corretto, ma suppongo che anche con inSampleSize la Bitmap sia enorme (circa 30 MB in DDMS).

Qualche idea come può farlo? Posso fare questi passaggi senza creare un oggetto bitmap? Intendo farlo su file system invece che su memoria RAM.

Questo è il codice corrente:

// The following function calculate the correct inSampleSize 
Bitmap image = Util.decodeSampledBitmapFromFile(imagePath, width,height); 
// compressing the image 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
image.compress(Bitmap.CompressFormat.JPEG, 40, baos); 
// encode image 
String encodedImage = Base64.encodeToString(baos.toByteArray(),Base64.DEFAULT)); 


public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     // Calculate ratios of height and width to requested height and width 
     final int heightRatio = Math.round((float) height/(float) reqHeight); 
     final int widthRatio = Math.round((float) width/(float) reqWidth); 

     // Choose the smallest ratio as inSampleSize value, this will guarantee 
     // a final image with both dimensions larger than or equal to the 
     // requested height and width. 
     inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
    } 

    return inSampleSize; 
} 

public static Bitmap decodeSampledBitmapFromFile(String path,int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(path, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeFile(path,options); 
} 
+0

facciamo attraverso u otterrà qualche idea http://developer.android.com/training/displaying-bitmaps/manage-memory.html –

+0

getBitmap(). recycle(); –

+0

Hai l'immagine in un file, giusto? Basta inviare questo file al server e apportare le necessarie trasformazioni lì. – Henry

risposta

46

si può saltare ARGB_8888, e utilizzare RGB_565 invece, e quindi dithering poi immagini per preservare la buona qualità

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = false; 
options.inPreferredConfig = Config.RGB_565; 
options.inDither = true; 
+0

Riduce la dimensione della bitmap 13 MB e funziona. Grazie mille! – alasarr

+0

Ottimo! Funziona! Grazie! – Ignacio

1

è necessario utilizzare BitmapFactory.Options con inJustDecodeBounds impostata su true. In questo modo è possibile caricare informazioni sulla bitmap e calcolare il valore per il downsampling (inSampleSize per esempio)

+0

L'ho già fatto e non funziona. – alasarr

+0

Mi piacerebbe vederlo. Puoi aggiornare il post con lo snippet di codice? – Blackbelt

+0

Ho appena aggiornato il post. Grazie! – alasarr

1

NON caricare l'immagine come bitmap, convertirla in un array, quindi inviarla.

invece:

leggerlo come un file, in formato JPG. Usa il file array di byte, per codificarlo e invia il file.

Caricandolo su bitmap, causerà inutilmente enormi problemi di memoria. Un'immagine, reperita in formato Bitmap, avrà una memoria ~ 20x o superiore a quella necessaria.

Sul lato server, sarà necessario trattarlo come un file. piuttosto che una bitmap.

Ecco un link per il caricamento di un file per byte []: Elegant way to read file into byte[] array in Java

+0

Ho bisogno di una bitmap, perché ho bisogno di ridimensionarlo e comprimerlo. La dimensione originale dell'immagine è di 12 MB e mi piacerebbe essere inviata al server circa 700 KB, non i 12 MB dell'immagine originale. – alasarr

+0

@alasarr Ah, mio ​​errore. devi campionarlo sbagliato. Vedi http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – Doomsknight

+0

@alasarr Solo così sei consapevole.Un'immagine '2400x2400', in formato bitmap, che usa' 2 byte 'per pixel, ha una dimensione di '11MB'. indipendentemente dal fatto che il formato jpg sia '700KB'. O nella rappresentazione '4 byte' è' 22MB' – Doomsknight

Problemi correlati