Как преобразовать большое растровое изображение (фотографию, сделанную камерой телефона) в строку Base64?
Как преобразовать большое растровое изображение (фотографию, сделанную камерой телефона) в строку Base64?
Ответы:
используйте следующий метод для преобразования растрового изображения в байтовый массив:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
для кодирования base64 из байтового массива используйте следующий метод
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
У меня есть быстрое решение. Просто создайте файл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);
Проблема с ответом 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. Вот как это сделать с помощью простого копирования и вставки (в 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()
}
}
}
}
В качестве бонуса качество вашего изображения должно быть немного улучшено за счет обхода повторного сжатия.
Теперь, когда большинство людей используют 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);
}
}