Giới thiệu
Bài viết này hướng dẫn cách chuyển đổi chuỗi Base64 thành Bitmap trên Android. Đây là thao tác ngược lại của encode, thường dùng khi nhận dữ liệu ảnh từ API (JSON), database, hoặc QR code.
Các bước thực hiện
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.
Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scaleType="centerInside"
android:contentDescription="Decoded bitmap" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Base64 string → Bitmap image"
android:textSize="16sp"
android:textStyle="bold|italic" />
</LinearLayout>
Bước 3: Viết code decode (src/MainActivity.java)
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Base64;
import android.widget.ImageView;
import java.io.ByteArrayOutputStream;
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
@SuppressLint("WrongThread")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.imageView);
// Demo: Encode một ảnh resource thành Base64, rồi decode lại
// Trong thực tế: Base64 string đến từ API/Database
new Thread(() -> {
// 1. Encode: Drawable → Bitmap → ByteArray → Base64 String
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
originalBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] imageBytes = baos.toByteArray();
String base64String = Base64.encodeToString(imageBytes, Base64.DEFAULT);
// 2. Decode: Base64 String → ByteArray → Bitmap
byte[] decodedBytes = Base64.decode(base64String, Base64.DEFAULT);
Bitmap decodedBitmap = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
// 3. Cập nhật UI trên Main Thread
runOnUiThread(() -> {
if (decodedBitmap != null) {
imageView.setImageBitmap(decodedBitmap);
}
});
}).start();
}
}
Bước 4: Manifest (androidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Chuẩn bị file image.png/jpg trong res/drawable/. Kết nối thiết bị, nhấn Run. Ảh sẽ hiển thị sau khi decode Base64.
Code tiện ích tái sử dụng (Utility Class)
public class BitmapBase64Utils {
/** Bitmap → Base64 String */
public static String bitmapToBase64(Bitmap bitmap, Bitmap.CompressFormat format, int quality) {
if (bitmap == null) return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(format, quality, baos);
byte[] bytes = baos.toByteArray();
return Base64.encodeToString(bytes, Base64.NO_WRAP); // NO_WRAP: không xuống dòng
}
/** Base64 String → Bitmap */
public static Bitmap base64ToBitmap(String base64String) {
if (base64String == null || base64String.isEmpty()) return null;
try {
// Xử lý Data URI scheme: "data:image/png;base64,xxxx"
if (base64String.contains(",")) {
base64String = base64String.substring(base64String.indexOf(",") + 1);
}
byte[] bytes = Base64.decode(base64String, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
} catch (IllegalArgumentException e) {
e.printStackTrace();
return null;
}
}
/** Base64 String → Bitmap với Options (giảm RAM cho ảnh lớn) */
public static Bitmap base64ToBitmap(String base64String, BitmapFactory.Options options) {
if (base64String == null) return null;
try {
byte[] bytes = Base64.decode(base64String, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
} catch (Exception e) {
return null;
}
}
/** Lưu Base64 string ra file ảnh */
public static boolean saveBase64ToFile(String base64String, File file) {
Bitmap bitmap = base64ToBitmap(base64String);
if (bitmap == null) return false;
try (FileOutputStream fos = new FileOutputStream(file)) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
return true;
} catch (IOException e) {
return false;
}
}
}
Các trường hợp thường gặp
| Nguồn Base64 | Định dạng | Xử lý |
|---|---|---|
| JSON API response | "image": "iVBORw0KGgoAAAANSUhEUg..." |
Decode trực tiếp |
| Data URI (HTML/CSS) | "data:image/png;base64,iVBORw0K..." |
Bỏ phần header trước dấu phẩy |
| Database (TEXT/BLOB) | Base64 thuần | Decode trực tiếp |
| QR Code chứa ảnh | Base64 nén | Decode, có thể cần resize |
Lưu ý hiệu năng & Bộ nhớ
- Base64 lớn hơn binary ~33%: Ảnh 1MB → Base64 ~1.33MB string.
- Decode trên Background Thread:
BitmapFactory.decodeByteArraytốn thời gian, gây ANR nếu ảnh lớn. - OOM Risk: Ảnh lớn (4000x3000) decode trực tiếp → crash. Dùng
inSampleSizetrongBitmapFactory.Options. - inMutable = true (API 19+) nếu cần vẽ lên bitmap sau khi decode.
- Base64.NO_WRAP: Không chèn newline (\n) mỗi 76 chars - chuẩn RFC 4648, phù hợp JSON.
Ví dụ decode an toàn cho ảnh lớn
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); // Tính inSampleSize để giảm kích thước (ví dụ max 1024px) options.inSampleSize = calculateInSampleSize(options, 1024, 1024); options.inJustDecodeBounds = false; options.inPreferredConfig = Bitmap.Config.RGB_565; // Tiết kiệm RAM Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
Kết luận
Chuyển Base64 ↔ Bitmap là kỹ năng cơ bản. Luôn nhớ: decode trên background thread, xử lý OOM cho ảnh lớn, dùng Base64.NO_WRAP cho JSON.