Как преобразовать большое растровое изображение (фотография, сделанная камерой телефона) в строку Base64?
Android Bitmap в строку Base64
Ответы (7)
используйте следующий метод для преобразования растрового изображения в массив байтов:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
для кодирования base64 из массива байтов используйте следующий метод
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
Base64.NO_WRAP
, если не хотите \n
в строке Base64.
- person NecipAllef; 05.05.2019
У меня есть быстрое решение. Просто создайте файл 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);
or
String base64String = ImageUtil.convert(bitmap);
base64Str.substring(base64Str.indexOf(",") + 1)
? Я не вижу, чтобы мои строки имели ,.
- person A1m; 24.02.2021
Проблема с ответом 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, но это немного сложнее, так как два потока всегда должны быть в разных потоках).
Попробуйте это, сначала масштабируйте изображение до необходимой ширины и высоты, просто передайте исходное растровое изображение, требуемую ширину и требуемую высоту следующему методу и получите взамен масштабированное растровое изображение:
Например: 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);
Все эти ответы неэффективны, поскольку они без необходимости декодируют растровое изображение, а затем повторно сжимают растровое изображение. Когда вы делаете фотографию на Android, она сохраняется в формате jpeg во временном файле, который вы указываете при подписке на документы для 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()
}
}
}
}
В качестве бонуса качество вашего изображения должно немного улучшиться за счет обхода повторного сжатия.
Теперь, когда большинство людей используют 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)
}
Используйте этот код..
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);
}
}