Android 位图到 Base64字符串

如何将一个大的位图(用手机摄像头拍摄的照片)转换为 Base64字符串?

147576 次浏览

使用以下方法将位图转换为字节数组:

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

使用以下方法从字节数组编码 base64

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

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,这并不是那么简单(您必须使用 管道输入流,但是这有点复杂,因为两个流必须总是在不同的线程中)。

我有快速解决方案。只要创建一个文件 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);

尝试这个,首先缩放你的图像到需要的宽度和高度,只需要传递你的原始位图,需要的宽度和需要的高度到下面的方法,并得到缩放位图作为回报:

例如: Bitmap scaledBitmap = getScaledBitmap (OrigalBitmap,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 上拍摄照片时,它会以 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()
}
}
}
}

作为奖励,您的图像质量应略有改善,由于绕过重新压缩。

用这个密码。

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

现在大多数人使用的是 Kotlin 而不是 Java,下面是 Kotlin 将位图转换成 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)
}