1. 程式人生 > 其它 >解決:Android base64 轉 bitmap 出現黑色背景

解決:Android base64 轉 bitmap 出現黑色背景

技術標籤:Android-技術篇Androidbase64bitmap

一、問題場景

將 png 圖片bitmap 轉為 base64,再將 base64 轉為 bitmap 後對比原圖,透明部分出現了黑色背景。

舉個例子:

有這樣一張圓角的圖片,圖片的四個角是透明的。

將其由 bitmap 轉為 base64,再轉為bitmap 後就會出現如下的情況:

明顯四個角的透明部分已經變為黑色。

二、問題原因

剛開始我也很納悶,怎麼同一張圖,轉為 base64 再轉回圖片就不一樣了呢!

後來發現是由於我將一張 png 的圖片轉回成了一張 jpg 的圖片,而 jpg 圖片是不帶透明通道的,如果還想帶著透明通道,轉回來的時候還是得轉為 png。

大家在日常開發中遇到需要將 base64 與 bitmap 之間互轉的需求,通常會直接在網上搜索一個工具類,卻忽略了網上的一些工具類只是寫死了將 bitmap 轉為jpg,而沒有支援由 bitmap 轉為 png。

如果你的圖片沒有透明部分,轉為 jpg 不會有問題。如果你的原圖存在透明部分,就要注意用合適的圖片格式去承載這張圖了!

三、解決方案

1、Kotlin 語言

object Base64Util {

    /**
     * bitmap 轉為 base64 
     * 
     * 說明:如果發現轉換後的圖片存在黑邊,可以將圖片格式改為 png
     * 
     * @param bitmap Bitmap?
     * @param compress Int              壓縮比例,範圍:0-100
     * @param format CompressFormat     圖片格式:JPEG、PNG、WEBP、WEBP_LOSSY、WEBP_LOSSLESS
     * @return String?
     */
    fun bitmap2Base64(bitmap: Bitmap?, compress: Int = 100, format: Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG): String? {
        if (bitmap == null) {
            return null
        }

        var result: String? = null
        var baos: ByteArrayOutputStream? = null
        try {
            try {
            baos = ByteArrayOutputStream()
            bitmap.compress(format, compress, baos)
            baos.flush()
            baos.close()
            val bitmapBytes = baos.toByteArray()
            result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT)
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                if (baos != null) {
                    baos.flush()
                    baos.close()
                }
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return result
    }

    /**
     * base64 轉為 bitmap
     * 
     * @param base64Data
     * @return
     */
    fun base642Bitmap(base64Data: String?): Bitmap? {
        if (TextUtils.isEmpty(base64Data)) {
            return null
        }

        return try {
            val bytes: ByteArray = Base64.decode(base64Data, Base64.DEFAULT)
            BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
        } catch (e: Exception) {
            null
        }
    }
}

呼叫:

val base64Data = Base64Util.bitmap2Base64(sourceBitmap, format = Bitmap.CompressFormat.PNG)

這樣就不會丟失透明度了!

2、Java 語言

本來想著寫到上面就算完了,但是為了Java Developer 能更直觀方便的閱讀,也方便拿來直接用,再附上一份轉為 Java 語言的程式碼:

public class Base64Util {
    /**
     * bitmap 轉為 base64
     *
     * 說明:如果發現轉換後的圖片存在黑邊,可以將圖片格式改為 png
     *
     * @param bitmap Bitmap?            圖片資源
     * @param compress Int              壓縮比例,範圍:0-100
     * @param format CompressFormat     圖片格式:JPEG、PNG、WEBP、WEBP_LOSSY、WEBP_LOSSLESS
     * @return String?                  base64 字串
     */
    public static String bitmap2Base64(Bitmap bitmap, int compress, Bitmap.CompressFormat format) {
        if (bitmap == null) {
            return null;
        }

        String result = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            bitmap.compress(format != null ? format : Bitmap.CompressFormat.JPEG, compress, baos);

            baos.flush();
            baos.close();

            byte[] bitmapBytes = baos.toByteArray();
            result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.flush();
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * base64 轉為 bitmap
     *
     * @param base64Data
     * @return
     */
    public static Bitmap base642Bitmap(String base64Data) {
        if (TextUtils.isEmpty(base64Data)) {
            return null;
        }
        
        byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }
}

呼叫方式:

Bitmap bitmap = Base64Util.bitmap2Base64(source, 100, Bitmap.CompressFormat.PNG);

搞定 !