Android Bitmap zu Base64 String

128

Wie konvertiere ich eine große Bitmap (mit der Kamera des Telefons aufgenommenes Foto) in eine Base64-Zeichenfolge?

Pankaj Singh
quelle
Wie möchten Sie das Bild codieren?
Ted Hopp
Sie stellen die falsche Frage. Mit der Kamera des Telefons aufgenommene Fotos werden als JPEG und nicht als Bitmaps gespeichert. Sie müssen das JPEG nur in eine Bitmap dekodieren, um es anzuzeigen. Sie werden weniger OutOfMemory-Fehler und unnötige Verarbeitung haben, wenn Sie meiner Antwort unten folgen.
Carson Holzheimer

Antworten:

301

Verwenden Sie die folgende Methode, um die Bitmap in ein Byte-Array zu konvertieren:

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

Verwenden Sie die folgende Methode, um base64 aus dem Byte-Array zu codieren

String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
jeet
quelle
Vielen Dank für die Lösung, ich habe den gleichen Code verwendet, aber meine codierte Zeichenfolge hat ... am Ende und ich denke, sie ist nicht vollständig konvertiert. Bitte sagen Sie mir, warum am Ende der Base 64-Zeichenfolge die Punkte (...) sind.
Pankaj Singh
@Pankaj Hallo kann mir sagen , wie u dieses Problem lösen, im gleichen Problem in meinem codierten String hat 3 Punkt mit Blick auf (...) kann u Hilfe bitte zu lösen , dass
Sachin Gurnani
5
@SachinGurnani - es zeigt ... weil der Logcat eine begrenzte String-Länge anzeigt und danach abgeschnitten wird. deshalb.
Pankaj Singh
Vielen Dank für Ihre Antwort Pankaj. Ich hatte dieses Problem am selben Tag selbst
gelöst
1
sollte dies in asynctask erfolgen? oder ist es in Ordnung, dies im Haupt-Thread zu tun?
n3wb
28

Ich habe eine schnelle Lösung. Erstellen Sie einfach eine DateiImageUtil.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);
    }

}

Verwendung:

Bitmap bitmap = ImageUtil.convert(base64String);

oder

String base64String = ImageUtil.convert(bitmap);
Vasilii Suricov
quelle
13

Das Problem mit der Antwort von jeet ist, dass Sie alle Bytes des Bildes in ein Byte-Array laden, wodurch die App auf Low-End-Geräten wahrscheinlich abstürzt. Stattdessen würde ich zuerst das Bild in eine Datei schreiben und es mit der Base64InputStream- Klasse von Apache lesen . Anschließend können Sie die Base64-Zeichenfolge direkt aus dem InputStream dieser Datei erstellen. Es wird so aussehen:

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

Wie Sie sehen können, funktioniert die obige Lösung stattdessen direkt mit Streams, sodass nicht alle Bytes in eine Variable geladen werden müssen, wodurch der Speicherbedarf erheblich verringert wird und die Wahrscheinlichkeit eines Absturzes bei Low-End-Geräten geringer ist. Es besteht immer noch das Problem, dass das Einfügen des Base64-Strings selbst in eine String-Variable keine gute Idee ist, da dies wiederum zu OutOfMemory-Fehlern führen kann. Aber zumindest haben wir den Speicherverbrauch halbiert, indem wir das Byte-Array eliminiert haben.

Wenn Sie den Schritt zum Schreiben in eine Datei überspringen möchten, müssen Sie den OutputStream in einen InputStream konvertieren, was nicht so einfach ist (Sie müssen PipedInputStream verwenden , dies ist jedoch etwas komplexer, da die beiden Streams immer erforderlich sind in verschiedenen Threads sein).

Tiago
quelle
2
Was ist hier Kodierung?
Animesh Mangla
5

Versuchen Sie dies, skalieren Sie zuerst Ihr Bild auf die erforderliche Breite und Höhe, übergeben Sie einfach Ihre ursprüngliche Bitmap, die erforderliche Breite und die erforderliche Höhe an die folgende Methode und erhalten Sie im Gegenzug eine skalierte Bitmap:

Zum Beispiel: 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);
}

Übergeben Sie nun einfach Ihre skalierte Bitmap an die folgende Methode und erhalten Sie im Gegenzug den base64-String:

Zum Beispiel: 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;
}

So dekodieren Sie die base64-Zeichenfolge zurück in das Bitmap-Image:

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

Alle diese Antworten sind ineffizient, da sie unnötigerweise in eine Bitmap dekodiert und dann die Bitmap erneut komprimiert werden. Wenn Sie ein Foto unter Android aufnehmen, wird es als JPEG in der temporären Datei gespeichert, die Sie angeben, wenn Sie den Android-Dokumenten folgen .

Sie sollten diese Datei direkt in eine Base64-Zeichenfolge konvertieren. Hier erfahren Sie, wie Sie dies in einfachem Kopieren und Einfügen (in Kotlin) tun. Beachten Sie, dass Sie den base64FilterStream schließen müssen, um den internen Puffer wirklich zu leeren.

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()
            }
        }
    }
}

Als Bonus sollte Ihre Bildqualität leicht verbessert werden, da die erneute Komprimierung umgangen wird.

Carson Holzheimer
quelle
1

Da die meisten Benutzer Kotlin anstelle von Java verwenden, finden Sie hier den Code in Kotlin zum Konvertieren einer Bitmap in eine base64-Zeichenfolge.

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)
    }
Reddy Tintaya
quelle
-2

Verwenden Sie diesen Code ..

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);
    }
}
Acme-Entwickler
quelle