web-dev-qa-db-fra.com

Android Bitmap to Base64 String

Comment convertir une grande image bitmap (photo prise avec l'appareil photo du téléphone) en chaîne Base64?

97
Pankaj Singh

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

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

coder en base64 à partir d'un tableau d'octets, utilisez la méthode suivante

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

J'ai une solution rapide. Il suffit de créer un fichier ImageUtil.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);
18
Vasilii Suricov

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 provoquera probablement le blocage de l'application dans les périphériques bas de gamme. Au lieu de cela, j’écrivais d’abord l’image dans un fichier et 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 constater, la solution ci-dessus fonctionne directement avec les flux, ce qui évite de charger tous les octets dans une variable, ce qui réduit considérablement l'encombrement de la mémoire et le risque de blocage des périphériques bas de gamme. Le problème persiste: il n'est pas judicieux de placer la chaîne Base64 elle-même dans une variable String, car cela pourrait 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 ignorer l'étape d'écriture dans un fichier, vous devez convertir le OutputStream en InputStream, ce qui n'est pas si simple à faire (vous devez utiliser PipedInputStream mais c'est un peu plus complexe que le deux flux doivent toujours être dans des threads différents).

11
Tiago

Essayez ceci: adaptez d'abord votre image à la largeur et à la hauteur requises, passez simplement le bitmap d'origine, la largeur requise et la hauteur requise à la méthode suivante, puis obtenez le bitmap mis à 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 redimensionné à la méthode suivante et obtenez une 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);
4
Ashwin

Toutes ces réponses sont inefficaces car elles décodent inutilement en bitmap puis recompressent le bitmap. Lorsque vous prenez une photo sur Android, elle est stockée sous forme de fichier jpeg dans le fichier temporaire que vous spécifiez lorsque vous suivez la documentation Android .

Ce que vous devez faire est de convertir directement ce fichier en chaîne Base64 . Voici comment procéder en copier-coller simple (en Kotlin).

fun convertImageFileToBase64(imageFile: File): String {

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

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

1
Carson Holzheimer