Android Bitmap для Base64 String

Как преобразовать большой битмап (фото, сделанный с помощью камеры телефона) в строку Base64?

Ответ 1

использовать следующий метод для преобразования битмапа в массив байтов:

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

для кодирования base64 из массива байтов используйте следующий метод

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

Ответ 2

У меня быстрое решение. Просто создайте файл 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);

Ответ 3

Проблема с ответом jeet заключается в том, что вы загружаете все байты изображения в массив байтов, что, скорее всего, приведет к краху приложения в младших устройствах. Вместо этого я сначала напишу изображение в файл и прочитаю его, используя класс Apache Base64InputStream. Затем вы можете создать строку Base64 непосредственно из InputStream этого файла. Он будет выглядеть следующим образом:

//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, но это немного сложнее, поскольку два потока всегда должны быть в разных потоках).

Ответ 4

Попробуйте это, сначала масштабируйте свое изображение до требуемой ширины и высоты, просто передайте исходное растровое изображение, требуемую ширину и требуемую высоту для следующего метода и получите в результате масштабированное растровое изображение:

Например: 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);

Ответ 5

Используйте getPixels, чтобы получить битмап как массив байтов. Затем вы можете использовать Base64.encodeToString для кодирования. Это будет работать только для уровня API 8 и выше. См. этот вопрос для более старых устройств.

Ответ 6

Все эти ответы неэффективны, так как они без необходимости декодируют в растровое изображение, а затем повторно сжимают растровое изображение. Когда вы делаете фотографию на Android, она сохраняется в формате JPEG в временном файле, который вы указываете, когда вы следуете документам по Android.

Что вам нужно сделать, это напрямую преобразовать этот файл в строку 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()
            }
        }
    }
}

В качестве бонуса, качество вашего изображения должно быть немного улучшено за счет обхода повторного сжатия.