android开发中对图片的处理方式汇总

1. LruCache 利用弱引用动态的管理内存(已经过时,但思想可以借鉴)

LruCache(Least Recently Used Cache) 全称最近最少使用算法,其主要思想是使用SoftReference(或者WeakReference),因为我们的缓存容量是有限的,它会面临一个问题:当有新的内容需要加入我们的缓存,但我们的缓存空闲的空间不足以放进新的内容时,我们就需要舍弃原有的部分内容从而腾出空间用来放新的内容。

在LruCache 中,我们使用url做key,bitmap做value,利用软引用的特性(在内存将满的时候会被垃圾回收器回收,如果还有可用内存,垃圾回收器不会)及时的回收内存,这种方式能够及时有效回收图片所占用的内存,但这些方法并未完全解决单个图片占用内存过大的问题,在程序运行的过程中,图片该多大还多大。我们只是控制在内存中存在图片对象的个数而已。

与Lru相似的还有Lfu,前者是最近最少使用,即淘汰最长时间未使用的对象;后者是最近最不常使用,即淘汰一段时间内使用最少的对象。比如我们缓存对象的顺序是:A B C B D A C A ,当需要淘汰一个对象时,如果采用LRU算法,则淘汰的是B,因为它是最长时间未被使用的。如果采用LFU算法,则淘汰的是D,因为在这段时间内它只被使用了一次,是最不经常使用的。

注意:对于SoftReference(软引用)或者WeakReference(弱引用)的Bitmap缓存方案,现在已经不推荐使用了。自Android2.3版本(API Level 9)开始,垃圾回收器更着重于对软/弱引用的回收。

与此种方法类似,我们可以使用硬盘缓存(DiskLruCache)来进行图片的管理,这种方法比LruCache 节省内存,但读取速度较慢(硬盘的读取速度是未知的)。

2. 按照一定规则压缩图片(以android为例)

Android中图片是以bitmap形式存在的,那么bitmap所占内存,直接影响到了应用所占内存大小。
bitmap所占内存大小计算方式:
图片长度 x 图片宽度 x 一个像素点占用的字节数
以下是图片的压缩格式:
![BitMap 格式类型](https://img-blog.csdn.net/20161215104040200?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXE1NjQwNDU4Njc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。

ALPHA_8 
表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度 

ARGB_4444 
表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节 

ARGB_8888 
表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节 

RGB_565 
表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节

2.1 质量压缩(android sdk 提供)

ByteArrayOutputStream baos = new ByteArrayOutputStream();  //内存流
bitmapOld.compress(CompressFormat.JPEG, quality, baos); //quality为压缩百分比
//quality=50,意为压缩为1/2
byte[] bytes = baos.toByteArray();
bitmapNew= BitmapFactory.decodeByteArray(bytes, 0, bytes.length);//生成图片对象

通过此种方式,图片的大小是没有变的,因为质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,这也是为什么该方法叫质量压缩方法。图片的长,宽,像素都不变,那么bitmap所占内存大小是不会变的。

但是bytes.length是随着quality变小而变小的。这样适合去传递二进制的图片数据,比如微信分享图片,要传入二进制数据过去,限制32kb之内。

如果是bit.compress(CompressFormat.PNG, quality, baos);这样的png格式,quality就没有作用了,bytes.length也不会变化,因为png图片是无损的,不能进行压缩。

2.2 采样率压缩(android sdk 提供)

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;     //inSampleSize 为压缩比         此处为1/2
bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/DCIM/Camera/test.jpg", options);

设置inSampleSize的值(int类型)后,假如设为2,则宽和高都为原来的1/2,宽高都减少了,图片总像素就减少了,自然内存也降低了。

Glide默认加载图片时是通过将图片转换成ImageView的大小后再加载。
Picasso默认是加载了全尺寸的图片到内存,然后让GPU来实时重绘大小(也可以手动设置或者将scaletype设置成   centerCrop等)。

2.3 缩放法压缩(martix,android sdk 提供)

Matrix matrix = new Matrix();
matrix.setScale(0.5f, 0.5f);
bm = Bitmap.createBitmap(bit, 0, 0, bit.getWidth(),bit.getHeight(), matrix, true);
通过上述代码,bitmap的长度和宽度分别缩小了一半,图片大小缩小了四分之一。 

2.4 RGB_565法

BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;  //将格式设置成RGB_565
bm = BitmapFactory.decodeFile(Environment
                    .getExternalStorageDirectory().getAbsolutePath()
                    + "/DCIM/Camera/test.jpg", options);
经过此种方式,图片大小直接缩小了一半,长度和宽度也没有变,相比argb_8888减少了一半的内存。

注意:由于ARGB_4444的画质惨不忍睹,一般假如对图片没有透明度要求的话,可以改成RGB_565,相比ARGB_8888将节省一半的内存开销。

Glide默认的Bitmap格式就是RGB_565
Picasso是ARGB_8888

2.5 createScaledBitmap

bitmapNew= Bitmap.createScaledBitmap(bitmapOld, 150, 150, true);

这里是将图片压缩成我们所期望的长度和宽度(150,150)。
图片的内存大小相应也发生了改变。

但是这里要说,如果用户期望的长度和宽度和原图长度宽度相差太多的话,图片会很不清晰。

android 中 Bitmap压缩都是围绕这个来做文章:Bitmap所占用的内存 = 图片长度 x 图片宽度 x 一个像素点占用的字节数。3个参数,任意减少一个的值,就达到了压缩的效果。

2.6 Bitmap.recycle() 用于不再使用的图片对象的处理

该方法不是真正降低图片内存的方法。主要目的是标记图片对象,方便回收图片对象的本地数据。

扫描二维码关注公众号,回复: 2705689 查看本文章

图片对象的本地数据占用的内存最大,而且与程序Java部分的内存是分开计算的。所以经常出现Java heap足够使用,而图片发生OutOfMemoryError的情况。在图片不使用时调用该方法,可以有效降低图片本地数据的峰值,从而减少OutOfMemoryError的概率。不过调用了recycle()的图片对象处于“废弃”状态,调用时会造成程序错误。所以在无法保证该图片对象绝对不会被再次调用的情况下,不建议使用该方法。

特别要注意已经用setImageBitmap(Bitmap img)方法分配给控件的图片对象(意为img存在其他地方的引用),可能会被系统类库调用,造成程序错误。

3.处理美工给的UI图 tinypng(网站)

一个很好的批处理压缩图片文件的网站(工具),可将图片压缩至70%左右。
网站链接:https://tinypng.com

经过测试,在妇儿医院1.0版本中,美工给的门诊主页Home切图原为1.3M,经过此网站工具压缩后图片文件大约为600K左右,原图和经过压缩后的图片在1080p手机上肉眼未见明显差别。

但这种方式只能处理美工给的切图,不能处理来自服务器的图片文件。

这里写图片描述
这里写图片描述

4.webP图片格式(android,ios均适用)

WebP图片格式,由谷歌于2010年推出的新一代图片格式,在压缩方面比当前JPEG格式更优越。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。Facebook Ebay等知名网站已经开始测试并使用WebP格式。

但WebP是一种有损压缩。相较编码JPEG文件,编码同样质量的WebP文件需要占用更多的计算资源。

谷歌表示,这种格式的主要优势在于高效率。他们发现,“在质量相同的情况下,WebP格式图像的体积要比JPEG格式图像小40%。谷歌浏览器已经支持webp格式,Opera在版本号Opera11.10后也增加了支持,然而火狐和ie暂时还不支持webp格式,可以采用flash插件来显示webp,当然这样会耗费一些性能。

美中不足的是,WebP格式图像的编码时间“比JPEG格式图像长8倍”(占用cpu,节省内存)。

分析人士认为,尽管WebP格式尚未像JPEG格式那样,得到各种软硬件的广泛支持,但谷歌推广这一格式的优势在于Chrome浏览器。这款谷歌开发的浏览器的市场份额已达10%以上。

桌面版Chrome可打开WebP格式。

常用的webp转换工具有:XnConvet,智图,ISparta,集成方法请自行百度。

http://www.bkjia.com/Androidjc/1019610.html

5 .图片上传 (推荐使用luban from github)

一款仿微信的图片压缩库,一般用作上传图片的压缩
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq564045867/article/details/53666893