Android位图到Base64字符串


128

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


您想如何编码图像?
Ted Hopp'2

您问错了问题。用手机相机拍摄的照片存储为jpeg,而不存储为位图。您只需要将jpeg解码为位图即可显示它。如果遵循以下我的回答,则将减少OutOfMemory错误和不必要的处理。
卡森·荷兹海默

Answers:


301

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

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

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

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

感谢您的解决方案,我使用了相同的代码,但是我的编码字符串末尾有...,我认为它没有完全转换,因此请告诉我为什么在Base 64字符串末尾是点(...)..
Pankaj辛格

@Pankaj嗨,你能告诉我你如何解决这个问题,我在编码字符串中面临的同样问题是3点(...)你能帮忙解决吗
Sachin Gurnani 2012

5
@SachinGurnani-它显示...,因为日志猫显示有限的字符串长度,然后将其截断。这就是为什么。
Pankaj Singh

感谢您的回复Pankaj。我当天就自己
解决了

1
应该在asynctask中完成吗?还是可以在主线程中执行此操作?
n3wb

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
这是什么编码?
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上拍摄照片时,该照片会以jpeg格式存储在您遵循android docs时指定的临时文件中。

您应该做的就是直接将该文件转换为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

现在大多数人使用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)
    }

-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);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.