Làm cách nào để chuyển đổi một Bitmap lớn (ảnh được chụp bằng máy ảnh của điện thoại) thành Chuỗi Base64?
Làm cách nào để chuyển đổi một Bitmap lớn (ảnh được chụp bằng máy ảnh của điện thoại) thành Chuỗi Base64?
Câu trả lời:
sử dụng phương pháp sau để chuyển bitmap thành mảng byte:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
để mã hóa base64 từ mảng byte sử dụng phương thức sau
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
Tôi có giải pháp nhanh. Chỉ cần tạo một tập tinImageUtil.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);
}
}
Sử dụng:
Bitmap bitmap = ImageUtil.convert(base64String);
hoặc là
String base64String = ImageUtil.convert(bitmap);
Vấn đề với câu trả lời của jeet là bạn tải tất cả các byte của hình ảnh vào một mảng byte, điều này có thể sẽ làm sập ứng dụng trong các thiết bị cấp thấp. Thay vào đó, trước tiên tôi sẽ ghi hình ảnh vào một tệp và đọc nó bằng lớp Base64InputStream của Apache . Sau đó, bạn có thể tạo chuỗi Base64 trực tiếp từ InputStream của tệp đó. Nó sẽ trông giống thế này:
//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();
Như bạn có thể thấy, giải pháp trên hoạt động trực tiếp với các luồng thay vào đó, tránh việc phải tải tất cả các byte vào một biến, do đó làm cho dung lượng bộ nhớ thấp hơn nhiều và ít có khả năng bị sập trong các thiết bị cấp thấp. Vẫn còn vấn đề là việc tự đặt chuỗi Base64 vào biến String không phải là ý hay, bởi vì, một lần nữa, nó có thể gây ra lỗi OutOfMemory. Nhưng ít nhất chúng ta đã giảm mức tiêu thụ bộ nhớ xuống một nửa bằng cách loại bỏ mảng byte.
Nếu bạn muốn bỏ qua bước ghi vào tệp, bạn phải chuyển đổi OutputStream thành InputStream, điều này không đơn giản để làm (bạn phải sử dụng PipedInputStream nhưng điều đó phức tạp hơn một chút vì hai luồng phải luôn luôn phức tạp được trong các chủ đề khác nhau).
Hãy thử điều này, trước tiên hãy chia tỷ lệ hình ảnh của bạn thành chiều rộng và chiều cao yêu cầu, chỉ cần chuyển bitmap gốc của bạn, chiều rộng yêu cầu và chiều cao cần thiết cho phương thức sau và nhận lại bitmap tỷ lệ:
Ví dụ: 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);
}
Bây giờ chỉ cần truyền bitmap tỷ lệ của bạn cho phương thức sau và nhận lại chuỗi base64:
Ví dụ: Chuỗi 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;
}
Để giải mã chuỗi base64 trở lại hình ảnh bitmap:
byte[] decodedByteArray = Base64.decode(base64String, Base64.NO_WRAP);
Bitmap decodedBitmap = BitmapFactory.decodeByteArray(decodedByteArray, 0, decodedString.length);
Tất cả các câu trả lời này đều không hiệu quả vì chúng không cần giải mã thành bitmap và sau đó giải nén lại bitmap. Khi bạn chụp ảnh trên Android, nó được lưu dưới dạng jpeg trong tệp tạm thời mà bạn chỉ định khi bạn theo tài liệu Android .
Những gì bạn nên làm là trực tiếp chuyển đổi tập tin đó thành chuỗi Base64. Đây là cách để làm điều đó trong bản sao chép dễ dàng (trong Kotlin). Lưu ý rằng bạn phải đóng base64FilterStream để thực sự xóa bộ đệm bên trong của nó.
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()
}
}
}
}
Là một phần thưởng, chất lượng hình ảnh của bạn sẽ được cải thiện một chút, do bỏ qua việc nén lại.
Bây giờ hầu hết mọi người sử dụng Kotlin thay vì Java, đây là mã trong Kotlin để chuyển đổi một bitmap thành chuỗi 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)
}
Sử dụng mã này ..
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);
}
}