大きなビットマップ(電話のカメラで撮影した写真)をBase64文字列に変換するにはどうすればよいですか?
次の方法を使用して、ビットマップをバイト配列に変換します。
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
バイト配列からbase64をエンコードするには、次の方法を使用します
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
迅速な解決策があります。ファイルを作成するだけで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);
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つのストリームは常に異なるスレッドにある必要があるため、複雑です)。
これを試して、最初に画像を必要な幅と高さにスケーリングし、元のビットマップ、必要な幅と高さを次のメソッドに渡し、スケーリングされたビットマップを取得します:
例: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);
}
スケーリングされたビットマップを次のメソッドに渡し、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);
これらの回答はすべて、不必要にビットマップにデコードしてからビットマップを再圧縮するため、非効率的です。 Androidで写真を撮ると、それは Android docs に従っているときに指定した一時ファイルにjpegとして保存されます。
そのファイルをBase64文字列に直接変換する必要があります。これを簡単なコピーアンドペースト(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()
}
}
}
}
ボーナスとして、再圧縮をバイパスするため、画像品質がわずかに改善されるはずです。