Jak przekonwertować dużą mapę bitową (zdjęcie zrobione aparatem telefonu) na ciąg Base64?
Jak przekonwertować dużą mapę bitową (zdjęcie zrobione aparatem telefonu) na ciąg Base64?
Odpowiedzi:
użyj następującej metody, aby przekonwertować bitmapę na tablicę bajtów:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
aby zakodować base64 z tablicy bajtów, użyj następującej metody
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
Mam szybkie rozwiązanie. Po prostu utwórz plikImageUtil.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);
}
}
Stosowanie:
Bitmap bitmap = ImageUtil.convert(base64String);
lub
String base64String = ImageUtil.convert(bitmap);
Problem z odpowiedzią jeeta polega na tym, że ładujesz wszystkie bajty obrazu do tablicy bajtów, co prawdopodobnie spowoduje awarię aplikacji na urządzeniach z niższej półki. Zamiast tego najpierw zapisałbym obraz do pliku i odczytał go za pomocą klasy Base64InputStream Apache . Następnie możesz utworzyć ciąg Base64 bezpośrednio z InputStream tego pliku. Będzie to wyglądać tak:
//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();
Jak widać, powyższe rozwiązanie działa bezpośrednio ze strumieniami zamiast tego, unikając konieczności ładowania wszystkich bajtów do zmiennej, dzięki czemu zużycie pamięci jest znacznie mniejsze i mniej prawdopodobne jest awarie w urządzeniach o niższej jakości. Nadal istnieje problem polegający na tym, że umieszczenie samego ciągu Base64 w zmiennej String nie jest dobrym pomysłem, ponieważ znowu może powodować błędy OutOfMemory. Ale przynajmniej zmniejszyliśmy zużycie pamięci o połowę, eliminując tablicę bajtów.
Jeśli chcesz pominąć krok zapisu do pliku, musisz przekonwertować OutputStream na InputStream, co nie jest takie proste (musisz użyć PipedInputStream, ale jest to trochę bardziej złożone, ponieważ dwa strumienie muszą zawsze być w różnych wątkach).
Spróbuj tego, najpierw przeskaluj obraz do wymaganej szerokości i wysokości, po prostu przekaż oryginalną bitmapę, wymaganą szerokość i wymaganą wysokość do następującej metody i otrzymaj w zamian skalowaną bitmapę:
Na przykład: 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);
}
Teraz po prostu przekaż skalowaną bitmapę do następującej metody i otrzymaj w zamian ciąg base64:
Na przykład: 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;
}
Aby zdekodować ciąg base64 z powrotem do obrazu bitmapowego:
byte[] decodedByteArray = Base64.decode(base64String, Base64.NO_WRAP);
Bitmap decodedBitmap = BitmapFactory.decodeByteArray(decodedByteArray, 0, decodedString.length);
Wszystkie te odpowiedzi są nieefektywne, ponieważ niepotrzebnie dekodują do mapy bitowej, a następnie ponownie ją kompresują. Kiedy robisz zdjęcie w systemie Android, jest ono przechowywane jako jpeg w pliku tymczasowym, który określasz podczas śledzenia dokumentów systemu Android .
To, co powinieneś zrobić, to bezpośrednio przekonwertować ten plik na ciąg Base64. Oto jak to zrobić w łatwym kopiowaniu i wklejaniu (w Kotlinie). Zauważ, że musisz zamknąć base64FilterStream, aby naprawdę opróżnić jego wewnętrzny bufor.
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()
}
}
}
}
Jako bonus, jakość obrazu powinna zostać nieznacznie poprawiona dzięki pominięciu ponownej kompresji.
Teraz, gdy większość ludzi używa Kotlin zamiast Javy, oto kod w Kotlinie do konwersji mapy bitowej na ciąg 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)
}
Użyj tego kodu ..
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);
}
}