Base64文字列へのAndroidビットマップ


128

大きなビットマップ(携帯電話のカメラで撮影した写真)をBase64文字列に変換するにはどうすればよいですか?


画像をどのようにエンコードしますか?
Ted Hopp、

あなたは間違った質問をしています。携帯電話のカメラで撮影した写真は、ビットマップではなくjpegとして保存されます。JPEGを表示するためには、JPEGをビットマップにデコードするだけです。以下の私の回答に従うと、OutOfMemoryエラーが少なくなり、不要な処理が発生します。
Carson Holzheimer

回答:


301

次のメソッドを使用して、ビットマップをバイト配列に変換します。

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

バイト配列からbase64をエンコードするには、次の方法を使用します

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

ソリューションのおかげで、私は同じコードを使用しているが、私のエンコードされた文字列が最後に...持っていると私はそれがベース64文字列の最後に(...)ドットであるなぜ私に教えてください...完全に変換されていないと思う
パンカジシン

@Pankajこんにちは、問題を解決する方法を教えてください。エンコードされた文字列で同じ問題に直面している場合、3つのドットがあります(...)それを解決するのに役立ちますか
Sachin Gurnani

5
@SachinGurnani-表示されます... logcatは限られた文字列の長さを表示し、その後は切り捨てられるためです。それが理由です。
Pankaj Singh 2012

ur respons Pankajをありがとう。私は同じ日にそれ自体この問題を解決しました
Sachin Gurnani 2012年

1
これは非同期タスクで行う必要がありますか?またはメインスレッドでこれを行うのは問題ありませんか?
n3wb 2014年

28

私は速い解決策を持っています。ファイルを作成するだけ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);
    }

}

使用法:

Bitmap bitmap = ImageUtil.convert(base64String);

または

String base64String = ImageUtil.convert(bitmap);

13

jeetの答えの問題は、画像のすべてのバイトをバイト配列にロードすることです。これにより、ローエンドデバイスのアプリがクラッシュする可能性があります。代わりに、まず画像をファイルに書き込み、ApacheのBase64InputStreamクラスを使用してそれを読み取ります。次に、そのファイルのInputStreamから直接Base64文字列を作成できます。次のようになります。

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

ご覧のように、上記のソリューションは代わりにストリームで直接機能するため、すべてのバイトを変数にロードする必要がなくなるため、メモリフットプリントがはるかに低くなり、ローエンドデバイスでクラッシュする可能性が低くなります。Base64文字列自体をString変数に入れることはお勧めできません。繰り返しますが、OutOfMemoryエラーが発生する可能性があるためです。ただし、少なくともバイト配列を削除することで、メモリ消費量を半分に削減できました。

ファイルへの書き込み手順をスキップする場合は、OutputStreamをInputStreamに変換する必要があります。これはそれほど簡単ではありません(PipedInputStreamを使用する必要がありますが、2つのストリームは常に別のスレッドにある)。


2
ここでエンコーディングとは何ですか?
Animesh Mangla

5

これを試して、最初に画像を必要な幅と高さにスケーリングし、元のビットマップ、必要な幅と高さを次のメソッドに渡して、スケーリングされたビットマップを返します。

例:ビットマップ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);
}

次に、スケーリングされたビットマップを次のメソッドに渡し、代わりにbase64文字列を取得します。

例: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;
}

base64文字列をビットマップ画像にデコードするには:

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

3

これらの回答はすべて、不必要にビットマップにデコードしてからビットマップを再圧縮するため、非効率的です。Androidで写真を撮ると、android docsをフォローしときに指定した一時ファイルにjpegとして保存されます。

あなたがすべきことは、そのファイルを直接Base64文字列に変換することです。これは、簡単なコピー/貼り付け(Kotlin)で行う方法です。内部バッファーを本当にフラッシュするには、base64FilterStreamを閉じる必要があることに注意してください。

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

おまけとして、再圧縮をバイパスするため、画像の品質が少し向上するはずです。


1

ほとんどの人がJavaではなくKotlinを使用するようになったので、ビットマップをbase64文字列に変換するためのKotlinのコードを次に示します。

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

このコードを使用してください。

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);
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.