zoukankan      html  css  js  c++  java
  • Android Base64转图片

    最近做一个项目里面有关于图片展示的需求,但是任性的后台跟我说没有图片服务器,只能给我base64让我自己转成图片,好吧,我忍,转就转吧。。

    首先第一步咱还是谦虚点上百度查查别人咋转的,结果似乎各位码友关于这方面的需求还是不多啊,查来查去普遍的是这样的:

    /** 
     * bitmap转为base64 
     * @param bitmap 
     * @return 
     */  
    public static String bitmapToBase64(Bitmap bitmap) {  
      
        String result = null;  
        ByteArrayOutputStream baos = null;  
        try {  
            if (bitmap != null) {  
                baos = new ByteArrayOutputStream();  
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, 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 base64ToBitmap(String base64Data) {  
        byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT);  
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);  
    }  

    楼主主要用到了base64转bitmap的方法,这个方法看上去没什么毛病,but。。。但是。。BitmapFactory.decodeByteArray这个方法是很邪恶的,BitmapFactory每次都会为新decode的bitmap分配内存,所以很容易造成oom,楼主为求真实性,手动刷新了几下我们的页面,然后就看着内存蹭蹭的往上涨,结果很快就oom了,所以这个所谓的往上代码并不可取,果断抛弃了,自己来改造一个,贴上自己的代码(Kotlin版本):

    object ImageUtil {
    
        private var mMemoryCache: LruCache<String, Bitmap> ?= null
        private var cacheSize:Int = 0
    
        /**
         * bitmap转为base64
         * @param bitmap
         * @return
         */
        public fun bitmapToBase64(bitmap: Bitmap): String {
            var result = ""
            var baos: ByteArrayOutputStream? = null
            try {
                if (bitmap != null) {
                    baos = ByteArrayOutputStream()
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, 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
         */
        public fun base64ToBitmap(base64Data: String): Bitmap? {
            if(cacheSize == 0){
                // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。
                // LruCache通过构造函数传入缓存值,以KB为单位。
                val maxMemory = Runtime.getRuntime().maxMemory() / 1024
                // 使用最大可用内存值的1/8作为缓存的大小。
                cacheSize = (maxMemory / 8).toInt()
            }
    
            if(mMemoryCache == null){
                mMemoryCache = object : LruCache<String, Bitmap>(cacheSize) {
                    override fun sizeOf(key: String?, bitmap: Bitmap?): Int {
                        // 重写此方法来衡量每张图片的大小,默认返回图片数量。
                        return bitmap!!.byteCount / 1024
                    }
                }
            }
    
            var bitmap: Bitmap? = null
            var imgByte: ByteArray? = null
            var inputStream:InputStream ?= null
            try {
                mMemoryCache?.get(base64Data)?.let {
                    bitmap = it
                }
                if(bitmap == null){
                    imgByte = Base64.decode(base64Data, Base64.DEFAULT)
                    val option = BitmapFactory.Options()
                    option.inSampleSize = 2
                    option.inTempStorage = ByteArray(5*1024*1024)
                    inputStream = ByteArrayInputStream(imgByte)
                    val softReference = SoftReference(BitmapFactory.decodeStream(inputStream, null, option))
                    bitmap = softReference.get()
                    softReference.clear()
                    mMemoryCache?.put(base64Data, bitmap)
                }
    
            } catch (e: Exception) {
                e.printStackTrace()
            }finally {
                imgByte = null
                try {
                    inputStream?.close()
                    System.gc()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
            return bitmap
        }
    
    }

    通过内存缓存机制加上软应用,保证同一张图片只decode一次,改完之后还算满意,基本上内存可以保持稳定,好了,先到这了,有啥写的不好的多多见谅,或者可以共同探讨。。

  • 相关阅读:
    洛谷P4175 网络管理
    洛谷P2605 基站选址
    洛谷P3723 礼物
    bzoj3771 Triple
    洛谷P3321 序列统计
    bzoj2194 快速傅里叶之二
    1109课堂内容整理
    响应式网页
    表单隐藏域有什么作用?
    1106课堂笔记
  • 原文地址:https://www.cnblogs.com/popqq520/p/9147400.html
Copyright © 2011-2022 走看看