Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีแปลง Bitmap เป็น Byte Array ใน Android

ภาพรวม

ตัวอย่างนี้สาธิตการแปลง Bitmap เป็น byte[] (Byte Array) ผ่าน ByteArrayOutputStream และ Bitmap.compress() เหมาะสำหรับการส่งรูปภาพผ่าน Network, บันทึกลง Database, หรือ SharedPreferences

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

Android Studio → File → New Project → Empty Activity

ขั้นตอนที่ 2: จัดรูปแบบหน้าจอ (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:id="@+id/rl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="24dp"
        android:text="Convert Bitmap to Byte Array" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/button"
        android:layout_marginTop="24dp"
        android:orientation="horizontal"
        android:gravity="center"
        android:weightSum="2">

        <ImageView
            android:id="@+id/ivSource"
            android:layout_width="0dp"
            android:layout_height="200dp"
            android:layout_weight="1"
            android:layout_marginEnd="8dp"
            android:scaleType="centerCrop"
            android:contentDescription="Original Image" />

        <ImageView
            android:id="@+id/ivCompressed"
            android:layout_width="0dp"
            android:layout_height="200dp"
            android:layout_weight="1"
            android:layout_marginStart="8dp"
            android:scaleType="centerCrop"
            android:contentDescription="Compressed Image" />

    </LinearLayout>

</RelativeLayout>

ขั้นตอนที่ 3: เตรียมรูปภาพทดสอบ

วางไฟล์รูปภาพชื่อ image.png ในโฟลเดอร์ assets/ (สร้างโฟลเดอร์ assets หากยังไม่มี: New → Folder → Assets Folder)

ขั้นตอนที่ 4: เขียนโค้ด MainActivity.java

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class MainActivity extends AppCompatActivity {

    private Button button;
    private ImageView ivSource, ivCompressed;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = findViewById(R.id.button);
        ivSource = findViewById(R.id.ivSource);
        ivCompressed = findViewById(R.id.ivCompressed);

        button.setOnClickListener(v -> convertBitmapToByteArray());
    }

    private void convertBitmapToByteArray() {
        try {
            // 1. โหลด Bitmap จาก Assets
            InputStream inputStream = getAssets().open("image.png");
            Bitmap originalBitmap = BitmapFactory.decodeStream(inputStream);
            inputStream.close();
            
            // แสดงรูปต้นฉบับ
            ivSource.setImageBitmap(originalBitmap);

            // 2. แปลง Bitmap เป็น Byte Array
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            
            // Compress: Format JPEG, Quality 80% (0-100)
            // PNG จะไม่สูญเสียคุณภาพแต่ไฟล์ใหญ่กว่า
            boolean success = originalBitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
            
            if (!success) {
                Toast.makeText(this, "Compression failed", Toast.LENGTH_SHORT).show();
                return;
            }

            byte[] byteArray = stream.toByteArray();
            stream.close();

            // 3. แปลงกลับจาก Byte Array เป็น Bitmap (เพื่อทดสอบ)
            Bitmap compressedBitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
            ivCompressed.setImageBitmap(compressedBitmap);

            // แสดงข้อมูล
            String info = String.format("Original: %d KB\nCompressed: %d KB\nQuality: 80%% JPEG",
                originalBitmap.getByteCount() / 1024,
                byteArray.length / 1024);
            Toast.makeText(this, info, Toast.LENGTH_LONG).show();

        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }
}

ขั้นตอนที่ 5: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">

    <!-- ไม่ต้อง Permission WRITE_EXTERNAL_STORAGE สำหรับ Assets -->
    <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>

การทดสอบ

รันแอป → กดปุ่ม "Convert Bitmap to Byte Array" → จะแสดงรูปต้นฉบับและรูปที่ Compress แล้ว พร้อมขนาดไฟล์

วิธีแปลง Bitmap เป็น Byte Array ใน Android วิธีแปลง Bitmap เป็น Byte Array ใน Android

CompressFormat เลือกอะไรดี?

Formatคุณภาพขนาดไฟล์ใช้เมื่อไหร่
JPEGLossy (เสื่อมสภาพ)เล็กรูปถ่าย, ส่งผ่าน Network
PNGLossless (ไม่เสื่อม)ใหญ่Logo, Icon, ใส่ Transparency
WEBPLossy/Losslessเล็กกว่า JPEG/PNGAPI 14+ Lossy, API 18+ Lossless

Quality Parameter (0-100)

  • 100: คุณภาพสูงสุด, ไฟล์ใหญ่ที่สุด
  • 80-90: สมดุลดี (แนะนำทั่วไป)
  • 50-70: ไฟล์เล็ก, คุณภาพยอมรับได้
  • <50: คุณภาพต่ำมาก, ไฟล์เล็กมาก

การใช้งานจริง: อัปโหลดรูปภาพไป Server

// ใช้กับ Retrofit/OkHttp
RequestBody requestBody = RequestBody.create(
    MediaType.parse("image/jpeg"), byteArray);

MultipartBody.Part imagePart = MultipartBody.Part.createFormData(
    "image", "photo.jpg", requestBody);

// API Call
Call call = apiService.uploadImage(imagePart);
call.enqueue(new Callback() {
    @Override
    public void onResponse(Call call, Response response) {
        // Success
    }
    @Override
    public void onFailure(Call call, Throwable t) {
        // Error
    }
});

บันทึกลง SharedPreferences (Base64)

import android.util.Base64;

// บันทึก
String base64Image = Base64.encodeToString(byteArray, Base64.NO_WRAP);
prefs.edit().putString("profile_image", base64Image).apply();

// อ่านกลับ
String savedBase64 = prefs.getString("profile_image", "");
if (!savedBase64.isEmpty()) {
    byte[] decoded = Base64.decode(savedBase64, Base64.NO_WRAP);
    Bitmap bitmap = BitmapFactory.decodeByteArray(decoded, 0, decoded.length);
    imageView.setImageBitmap(bitmap);
}

⚠️ ข้อควรระวัง

  • Bitmap ขนาดใหญ่ (เช่น 4000x3000) อาจทำให้ OOM (OutOfMemoryError) → ใช้ inSampleSize ลดขนาดก่อน Decode
  • Byte Array ใหญ่เกิน 1MB ไม่ควรเก็บใน SharedPreferences (ช้า, ขนาดจำกัด)
  • ใช้ Bitmap.recycle() (API < 21) หรือให้ GC จัดการ (API 21+)
  • ปิด Stream ทุกครั้ง (try-with-resources แนะนำ)

สำหรับ Kotlin (Extension)

// Extension Function
fun Bitmap.toByteArray(format: Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG, quality: Int = 80): ByteArray {
    val stream = ByteArrayOutputStream()
    compress(format, quality, stream)
    return stream.toByteArray()
}

// ใช้งาน
val byteArray = bitmap.toByteArray(Bitmap.CompressFormat.WEBP, 90)