Растровое изображение Android в строку Base64

128

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

Панкадж Сингх
источник
Как вы хотите закодировать изображение?
Тед Хопп
Вы задаете неправильный вопрос. Фотографии, сделанные камерой телефона, сохраняются в формате jpeg, а не как растровые изображения. Вам нужно только декодировать jpeg в растровое изображение, чтобы отобразить его. У вас будет меньше ошибок OutOfMemory и ненужной обработки, если вы последуете моему ответу ниже.
Carson Holzheimer

Ответы:

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 Singh
@Pankaj Привет, ты можешь рассказать мне, как решить эту проблему, я столкнулся с той же проблемой в моей закодированной строке с 3 точками (...), пожалуйста, помогите решить это
Сачин Гурнани
5
@SachinGurnani - он показывает ... потому что logcat показывает ограниченную длину строки, а затем ее усеченную. поэтому.
Панкадж Сингх
Спасибо за твой отзыв, Панкадж. я решил эту проблему в тот же день
Сачин Гурнани
1
следует ли это делать в асинхронной задаче? или это нормально делать в основном потоке?
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 . Затем вы можете создать строку 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, но это немного сложнее, поскольку два потока всегда должны быть в разных темах).

Tiago
источник
2
Что здесь за кодирование?
Animesh Mangla
5

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

Например: 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);
Ashwin
источник
3

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

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