ภาพรวม
บทความนี้สาธิตวิธีแปลง Drawable เป็น Bitmap ใน Android ซึ่งเป็นการทำงานที่พบบ่อยเมื่อต้องการ: บันทึกรูปภาพ, แชร์รูป, อัปโหลด, ประมวลผลภาพ (Image Processing), หรือแสดงใน View ที่รับเฉพาะ Bitmap
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
สร้างโปรเจกต์ Android ใหม่ใน Android Studio
ขั้นตอนที่ 2: ออกแบบ Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:gravity="center"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginBottom="16dp"
android:scaleType="centerCrop"
android:src="@drawable/sample_image"
android:contentDescription="Sample Image" />
<Button
android:id="@+id/btnConvert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="แปลง Drawable → Bitmap" />
<TextView
android:id="@+id/tvInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textSize="14sp" />
</LinearLayout>
ขั้นตอนที่ 3: เขียนโค้ด MainActivity (src/MainActivity.java) - ครอบคลุมทุกกรณี
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private TextView tvInfo;
private Button btnConvert;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.imageView);
tvInfo = findViewById(R.id.tvInfo);
btnConvert = findViewById(R.id.btnConvert);
btnConvert.setOnClickListener(v -> convertDrawableToBitmap());
}
private void convertDrawableToBitmap() {
// ดึง Drawable จาก ImageView (หรือ Resources)
Drawable drawable = imageView.getDrawable();
// หรือ: Drawable drawable = ContextCompat.getDrawable(this, R.drawable.sample_image);
if (drawable == null) {
Toast.makeText(this, "ไม่พบ Drawable", Toast.LENGTH_SHORT).show();
return;
}
Bitmap bitmap = drawableToBitmap(drawable);
if (bitmap != null) {
// แสดงผล: ตั้งค่า Bitmap กลับเข้า ImageView (เพื่อยืนยัน)
imageView.setImageBitmap(bitmap);
// แสดงข้อมูล
String info = String.format(
"Bitmap Info:\nWidth: %d px\nHeight: %d px\nConfig: %s\nByte Count: %d KB",
bitmap.getWidth(), bitmap.getHeight(),
bitmap.getConfig(), bitmap.getByteCount() / 1024
);
tvInfo.setText(info);
Toast.makeText(this, "แปลงสำเร็จ!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "แปลงไม่สำเร็จ", Toast.LENGTH_SHORT).show();
}
}
/**
* แปลง Drawable ทุกประเภทเป็น Bitmap
* รองรับ: BitmapDrawable, VectorDrawable, ShapeDrawable, LayerDrawable, 9-patch, etc.
*/
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) return null;
// กรณีที่ 1: เป็น BitmapDrawable อยู่แล้ว
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
// กรณีที่ 2: VectorDrawable (API 21+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && drawable instanceof VectorDrawable) {
return vectorDrawableToBitmap((VectorDrawable) drawable);
}
// กรณีที่ 3: Drawable อื่นๆ (Shape, Layer, Gradient, 9-patch, etc.)
// สร้าง Bitmap ขนาดเท่า Intrinsic Size
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
// Fallback หาก Intrinsic Size เป็น -1 (ไม่มีขนาดคงที่)
if (width <= 0) width = 100;
if (height <= 0) height = 100;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// ตั้ง bounds ให้ Drawable แล้ววาดลง Canvas
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
// แปลง VectorDrawable เป็น Bitmap (API 21+)
private static Bitmap vectorDrawableToBitmap(VectorDrawable vectorDrawable) {
int width = vectorDrawable.getIntrinsicWidth();
int height = vectorDrawable.getIntrinsicHeight();
if (width <= 0) width = 100;
if (height <= 0) height = 100;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
return bitmap;
}
// ==================== เพิ่มเติม: วิธีอื่นๆ ====================
/**
* โหลดจาก Resources โดยตรงเป็น Bitmap (ไม่ผ่าน Drawable)
*/
private Bitmap loadBitmapFromResources(int resId) {
return BitmapFactory.decodeResource(getResources(), resId);
}
/**
* แปลง Bitmap กลับเป็น Drawable
*/
private void bitmapToDrawableExample(Bitmap bitmap) {
// สำหรับ API 22+
android.graphics.drawable.BitmapDrawable drawable =
new android.graphics.drawable.BitmapDrawable(getResources(), bitmap);
imageView.setImageDrawable(drawable);
}
/**
* Resize Bitmap (ย่อ/ขยาย)
*/
private Bitmap resizeBitmap(Bitmap source, int newWidth, int newHeight) {
return Bitmap.createScaledBitmap(source, newWidth, newHeight, true);
}
}
ขั้นตอนที่ 4: 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>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
สรุปวิธีแปลงตามประเภท Drawable
| ประเภท Drawable | วิธีแปลง | หมายเหตุ |
|---|---|---|
| BitmapDrawable | ((BitmapDrawable) drawable).getBitmap() | เร็วที่สุด ไม่ต้องสร้างใหม่ |
| VectorDrawable (API 21+) | วาดลง Canvas ด้วย vectorDrawable.draw(canvas) | ต้องระบุขนาด (Intrinsic หรือกำหนดเอง) |
| ShapeDrawable, GradientDrawable, LayerDrawable, 9-patch | วาดลง Canvas ทั่วไป | ต้อง setBounds ก่อน draw |
| ColorDrawable | สร้าง Bitmap แล้ว fill สี | ไม่มี Intrinsic Size |
Best Practices
- Recycle Bitmap: ใช้
bitmap.recycle()เมื่อไม่ใช้แล้ว (API < 19) หรือ ให้ GC จัดการ (API 19+) - inSampleSize: ใช้
BitmapFactory.Options.inSampleSizeโหลดรูปขนาดเล็กลงหน่วยความจำ - Mutable Bitmap: ต้องการ Edit Pixel ใช้
Bitmap.createBitmap(width, height, Config.ARGB_8888)(mutable by default) - Thread Safety: Bitmap Operations ควรทำใน Background Thread
- Memory Leak: ไม่เก็บ Bitmap reference ใน Static Field
การใช้งานจริง (Use Cases)
- Share Image:
Intent.ACTION_SENDต้องการ Bitmap/Uri - Save to Gallery:
MediaStore.Images.Media.insertImage()รับ Bitmap - Image Processing: OpenCV, RenderScript, ML Kit ต้องการ Bitmap Input
- Custom View Drawing: Canvas.drawBitmap()
- Notification Large Icon:
NotificationCompat.Builder.setLargeIcon(bitmap)