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