Android Bitmap для рядка Base64


128

Як перетворити велику растрову карту (фотографію, зроблену за допомогою камери телефону), у рядок Base64?


Як ви хочете кодувати зображення?
Тед Хопп

Ви ставите неправильне запитання. Фотографії, зроблені за допомогою камери телефону, зберігаються як jpeg, а не растрові. Вам потрібно лише розшифрувати jpeg до растрової карти з метою його відображення. У вас буде менше помилок OutOfMemory та непотрібна обробка, якщо ви будете слідувати моїй відповіді нижче.
Карсон

Відповіді:


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 крапки (...), можеш, будь ласка, допоможеш вирішити це
Сачін Гурнані

5
@SachinGurnani - це показує ... тому що logcat демонструє обмежений String lenth і після цього його усічений. ось чому.
Панкай Сінгх

Дякую за ур відповідь Панкай. Я виховував це питання в той самий день
Сачін Гурнані

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 полягає в тому, що ви завантажуєте всі байти зображення в байтовий масив, що, швидше за все, призведе до збою програми на пристроях низького класу. Натомість я б спершу записав зображення у файл та прочитав його, використовуючи клас Base64InputStream Apache . Тоді ви можете створити рядок 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, але це трохи складніше, тому що два потоки повинні завжди бути в різних нитках).


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 (масштабованаBitmap);

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 у файлі temp, який ви вказуєте, коли ви стежите за документами Android .

Що потрібно зробити, це безпосередньо перетворити цей файл у рядок Base64. Ось як це зробити в простому копію-вставлення (в Котліні). Зверніть увагу, ви повинні закрити 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);
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.