ฉันจะแปลง Bitmap ขนาดใหญ่ (ภาพที่ถ่ายด้วยกล้องของโทรศัพท์) เป็นสตริง Base64 ได้อย่างไร
ฉันจะแปลง Bitmap ขนาดใหญ่ (ภาพที่ถ่ายด้วยกล้องของโทรศัพท์) เป็นสตริง 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 (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 ในไฟล์ temp ที่คุณระบุเมื่อคุณทำตามเอกสารหุ่นยนต์
สิ่งที่คุณควรทำคือแปลงไฟล์นั้นเป็นสตริง 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);
}
}