Растровое изображение Android в строку Base64 - PullRequest
109 голосов
/ 10 февраля 2012

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

Ответы [ 5 ]

254 голосов
/ 10 февраля 2012

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

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

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

String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
21 голосов
/ 08 декабря 2016

У меня есть быстрое решение. Просто создайте файл 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);
12 голосов
/ 22 июля 2014

Проблема с ответом 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 голосов
/ 08 июня 2017

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

Например: 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);
1 голос
/ 05 февраля 2019

Все эти ответы неэффективны, поскольку они без необходимости декодируются в растровое изображение, а затем повторно сжимают растровое изображение.Когда вы делаете фотографию на 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()
            }
        }
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...