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一次,改完之后还算满意,基本上内存可以保持稳定,好了,先到这了,有啥写的不好的多多见谅,或者可以共同探讨。。

  • 相关阅读:
    百度之星资格赛1001——找规律——大搬家
    HDU1025——LIS——Constructing Roads In JGShining's Kingdom
    DP(递归打印路径) UVA 662 Fast Food
    递推DP UVA 607 Scheduling Lectures
    递推DP UVA 590 Always on the run
    递推DP UVA 473 Raucous Rockers
    博弈 HDOJ 4371 Alice and Bob
    DFS(深度) hihoCoder挑战赛14 B 赛车
    Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2)
    DP(DAG) UVA 437 The Tower of Babylon
  • 原文地址:https://www.cnblogs.com/popqq520/p/9147400.html
Copyright © 2011-2022 走看看