欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

解决:Android base64 转 bitmap 出现黑色背景

程序员文章站 2022-06-20 21:02:16
...

一、问题场景

将 png 图片 bitmap 转为 base64,再将 base64 转为 bitmap 后对比原图,透明部分出现了黑色背景。

举个例子:

解决:Android base64 转 bitmap 出现黑色背景

有这样一张圆角的图片,图片的四个角是透明的。

将其由 bitmap 转为 base64,再转为 bitmap 后就会出现如下的情况:

解决:Android 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);

搞定 !