Bitmap Android en chaîne Base64

128

Comment convertir un grand Bitmap (photo prise avec l'appareil photo du téléphone) en une chaîne Base64?

Pankaj Singh
la source
Comment voulez-vous encoder l'image?
Ted Hopp
Vous posez la mauvaise question. Les photos prises avec l'appareil photo du téléphone sont stockées au format jpeg et non au format bitmap. Il vous suffit de décoder le jpeg en bitmap dans le but de l'afficher. Vous aurez moins d'erreurs OutOfMemory et un traitement inutile si vous suivez ma réponse ci-dessous.
Carson Holzheimer

Réponses:

301

utilisez la méthode suivante pour convertir le bitmap en tableau d'octets:

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

pour encoder base64 à partir d'un tableau d'octets, utilisez la méthode suivante

String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
jeet
la source
Merci pour la solution, j'ai utilisé le même code mais ma chaîne encodée a ... à la fin et je pense qu'elle n'est pas complètement convertie alors dites-moi pourquoi à la fin de la chaîne Base 64 se trouvent les points (...) ..
Pankaj Singh
@Pankaj Salut pouvez-vous me dire comment vous résolvez ce problème, je suis confronté au même problème dans ma chaîne codée a 3 points (...) pouvez-vous s'il vous plaît aider à résoudre cela
Sachin Gurnani
5
@SachinGurnani - il montre ... parce que le logcat montre une longueur de chaîne limitée et après cela, elle est tronquée. c'est pourquoi.
Pankaj Singh
Merci pour votre réponse Pankaj.
J'avais résolu
1
cela doit-il être fait dans asynctask? ou est-ce bien de le faire dans le fil principal?
n3wb
28

J'ai une solution rapide. Créez simplement un fichierImageUtil.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);
    }

}

Usage:

Bitmap bitmap = ImageUtil.convert(base64String);

ou

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

Le problème avec la réponse de jeet est que vous chargez tous les octets de l'image dans un tableau d'octets, ce qui plantera probablement l'application dans les appareils bas de gamme. Au lieu de cela, j'écrirais d'abord l'image dans un fichier et je la lisais à l'aide de la classe Base64InputStream d'Apache . Ensuite, vous pouvez créer la chaîne Base64 directement à partir du InputStream de ce fichier. Il ressemblera à ceci:

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

Comme vous pouvez le voir, la solution ci-dessus fonctionne directement avec les flux à la place, évitant d'avoir à charger tous les octets dans une variable, rendant ainsi l'empreinte mémoire beaucoup plus faible et moins susceptible de planter dans les appareils bas de gamme. Il y a toujours le problème que placer la chaîne Base64 elle-même dans une variable String n'est pas une bonne idée, car, encore une fois, cela peut provoquer des erreurs OutOfMemory. Mais au moins, nous avons réduit de moitié la consommation de mémoire en éliminant le tableau d'octets.

Si vous souhaitez sauter l'étape d'écriture dans un fichier, vous devez convertir OutputStream en InputStream, ce qui n'est pas si simple à faire (vous devez utiliser PipedInputStream mais c'est un peu plus complexe car les deux flux doivent toujours être dans différents threads).

Tiago
la source
2
Qu'est-ce que l'encodage ici?
Animesh Mangla
5

Essayez ceci, mettez d'abord votre image à l'échelle à la largeur et à la hauteur requises, passez simplement votre bitmap d'origine, la largeur requise et la hauteur requise à la méthode suivante et obtenez une image bitmap mise à l'échelle en retour:

Par exemple: 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);
}

Maintenant, passez simplement votre bitmap mis à l'échelle à la méthode suivante et obtenez la chaîne base64 en retour:

Par exemple: 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;
}

Pour décoder la chaîne base64 en image bitmap:

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

Toutes ces réponses sont inefficaces car elles décodent inutilement un bitmap, puis recompressent le bitmap. Lorsque vous prenez une photo sur Android, elle est stockée au format jpeg dans le fichier temporaire que vous spécifiez lorsque vous suivez les documents Android .

Ce que vous devez faire est de convertir directement ce fichier en une chaîne Base64. Voici comment faire cela en simple copier-coller (dans Kotlin). Notez que vous devez fermer base64FilterStream pour vraiment vider sa mémoire tampon interne.

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

En prime, la qualité de votre image devrait être légèrement améliorée, en raison du contournement de la recompression.

Carson Holzheimer
la source
1

Maintenant que la plupart des gens utilisent Kotlin au lieu de Java, voici le code de Kotlin pour convertir un bitmap en une chaîne 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)
    }
Reddy Tintaya
la source
-2

Utilisez ce 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);
    }
}
Développeurs Acme
la source