Come si converte una bitmap di grandi dimensioni (foto scattata con la fotocamera del telefono) in una stringa Base64?
Come si converte una bitmap di grandi dimensioni (foto scattata con la fotocamera del telefono) in una stringa Base64?
Risposte:
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);
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);
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).
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);
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.
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)
}
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);
}
}