Bitmap Android su stringa Base64


128

Come si converte una bitmap di grandi dimensioni (foto scattata con la fotocamera del telefono) in una stringa Base64?


Come vuoi codificare l'immagine?
Ted Hopp

Stai facendo la domanda sbagliata. Le foto scattate con la fotocamera del telefono vengono memorizzate come jpeg, non come bitmap. Hai solo bisogno di decodificare il jpeg in una bitmap allo scopo di visualizzarlo. Avrai meno errori OutOfMemory e un'elaborazione inutile se segui la mia risposta di seguito.
Carson Holzheimer

Risposte:


301

utilizzare il seguente metodo per convertire bitmap in array di byte:

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();

per codificare base64 da un array di byte utilizzare il seguente metodo

String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);

Grazie per la soluzione, ho usato lo stesso codice ma la mia stringa codificata ha ... alla fine e penso che non sia stata convertita completamente quindi per favore dimmi perché alla fine della stringa Base 64 ci sono i punti (...) ..
Pankaj Singh

@Pankaj Ciao, puoi dirmi come risolvi il problema, sto affrontando lo stesso problema nella mia stringa codificata ha 3 punti (...) puoi per favore aiutarci a risolverlo
Sachin Gurnani

5
@SachinGurnani - mostra ... perché il logcat mostra una lunghezza di stringa limitata e dopo di ciò è troncata. Ecco perchè.
Pankaj Singh

Grazie per la tua risposta Pankaj. Ho risolto questo problema lo stesso giorno
Sachin Gurnani il

1
dovrebbe essere fatto in asynctask? o va bene farlo nel thread principale?
n3wb

28

Ho una soluzione veloce. Basta creare un fileImageUtil.java

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import java.io.ByteArrayOutputStream;

public class ImageUtil
{
    public static Bitmap convert(String base64Str) throws IllegalArgumentException
    {
        byte[] decodedBytes = Base64.decode(
            base64Str.substring(base64Str.indexOf(",")  + 1),
            Base64.DEFAULT
        );

        return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
    }

    public static String convert(Bitmap bitmap)
    {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);

        return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
    }

}

Uso:

Bitmap bitmap = ImageUtil.convert(base64String);

o

String base64String = ImageUtil.convert(bitmap);

13

Il problema con la risposta di jeet è che carichi tutti i byte dell'immagine in un array di byte, che probabilmente bloccherà l'app nei dispositivi di fascia bassa. Invece, vorrei prima scrivere l'immagine su un file e leggerla utilizzando la classe Base64InputStream di Apache . Quindi puoi creare la stringa Base64 direttamente dall'InputStream di quel file. Sarà simile a questo:

//Don't forget the manifest permission to write files
final FileOutputStream fos = new FileOutputStream(yourFileHere); 
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);

fos.close();

final InputStream is = new Base64InputStream( new FileInputStream(yourFileHere) );

//Now that we have the InputStream, we can read it and put it into the String
final StringWriter writer = new StringWriter();
IOUtils.copy(is , writer, encoding);
final String yourBase64String = writer.toString();

Come puoi vedere, la soluzione di cui sopra funziona invece direttamente con i flussi, evitando la necessità di caricare tutti i byte in una variabile, rendendo quindi l'impronta di memoria molto più bassa e meno probabile che si blocchi nei dispositivi di fascia bassa. C'è ancora il problema che mettere la stessa stringa Base64 in una variabile String non è una buona idea, perché, ancora una volta, potrebbe causare errori OutOfMemory. Ma almeno abbiamo dimezzato il consumo di memoria eliminando l'array di byte.

Se vuoi saltare il passaggio di scrittura su file, devi convertire OutputStream in un InputStream, che non è così semplice da fare (devi usare PipedInputStream ma è un po 'più complesso in quanto i due flussi devono sempre essere in thread diversi).


2
Che cos'è la codifica qui?
Animesh Mangla

5

Prova questo, prima ridimensiona l'immagine alla larghezza e all'altezza richieste, passa semplicemente la bitmap originale, la larghezza richiesta e l'altezza richiesta al seguente metodo e ottieni in cambio la bitmap scalata:

Ad esempio: Bitmap scaledBitmap = getScaledBitmap (originalBitmap, 250, 350);

private Bitmap getScaledBitmap(Bitmap b, int reqWidth, int reqHeight)
{
    int bWidth = b.getWidth();
    int bHeight = b.getHeight();

    int nWidth = bWidth;
    int nHeight = bHeight;

    if(nWidth > reqWidth)
    {
        int ratio = bWidth / reqWidth;
        if(ratio > 0)
        {
            nWidth = reqWidth;
            nHeight = bHeight / ratio;
        }
    }

    if(nHeight > reqHeight)
    {
        int ratio = bHeight / reqHeight;
        if(ratio > 0)
        {
            nHeight = reqHeight;
            nWidth = bWidth / ratio;
        }
    }

    return Bitmap.createScaledBitmap(b, nWidth, nHeight, true);
}

Ora passa semplicemente la tua bitmap scalata al seguente metodo e ottieni in cambio la stringa base64:

Ad esempio: String base64String = getBase64String (scaledBitmap);

private String getBase64String(Bitmap bitmap)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);

    byte[] imageBytes = baos.toByteArray();

    String base64String = Base64.encodeToString(imageBytes, Base64.NO_WRAP);

    return base64String;
}

Per decodificare la stringa base64 in un'immagine bitmap:

byte[] decodedByteArray = Base64.decode(base64String, Base64.NO_WRAP);
Bitmap decodedBitmap = BitmapFactory.decodeByteArray(decodedByteArray, 0, decodedString.length);

3

Tutte queste risposte sono inefficienti in quanto si decodificano inutilmente in una bitmap e quindi ricomprimono la bitmap. Quando scatti una foto su Android, viene memorizzata come jpeg nel file temporaneo specificato quando segui i documenti Android .

Quello che dovresti fare è convertire direttamente quel file in una stringa Base64. Ecco come farlo con un semplice copia-incolla (in Kotlin). Nota che devi chiudere base64FilterStream per svuotare veramente il suo buffer interno.

fun convertImageFileToBase64(imageFile: File): String {

    return FileInputStream(imageFile).use { inputStream ->
        ByteArrayOutputStream().use { outputStream ->
            Base64OutputStream(outputStream, Base64.DEFAULT).use { base64FilterStream ->
                inputStream.copyTo(base64FilterStream)
                base64FilterStream.close()
                outputStream.toString()
            }
        }
    }
}

Come bonus, la qualità dell'immagine dovrebbe essere leggermente migliorata, grazie al bypass della ricompressione.


1

Ora che la maggior parte delle persone usa Kotlin invece di Java, ecco il codice in Kotlin per convertire una bitmap in una stringa base64.

import java.io.ByteArrayOutputStream

private fun encodeImage(bm: Bitmap): String? {
        val baos = ByteArrayOutputStream()
        bm.compress(Bitmap.CompressFormat.JPEG, 100, baos)
        val b = baos.toByteArray()
        return Base64.encodeToString(b, Base64.DEFAULT)
    }

-2

Usa questo codice ..

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import java.io.ByteArrayOutputStream;

public class ImageUtil 
{ 
    public static Bitmap convert(String base64Str) throws IllegalArgumentException 
    { 
        byte[] decodedBytes = Base64.decode( base64Str.substring(base64Str.indexOf(",") + 1), Base64.DEFAULT );
        return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
    } 

    public static String convert(Bitmap bitmap) 
    { 
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
        return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.