解決:Android base64 轉 bitmap 出現黑色背景
阿新 • • 發佈:2021-01-02
技術標籤: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);
搞定 !