Android Bitmap 全面解析(一)加载大尺寸图片
压缩原因:
1.imageview大小如果是200*300那么加载个2000*3000的图片到内存中显然是浪费可耻滴行为;
2.最重要的是图片过大时直接加载原图会造成OOM异常(out of memory内存溢出)
所以一般对于大图我们需要进行下压缩处理
权威处理方法参考 安卓开发者中心的大图片处理教程
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
看不懂英文的话木有关系,本篇会有介绍
主要处理思路是:
1.获取图片的像素宽高(不加载图片至内存中,所以不会占用资源)
2.计算需要压缩的比例
3.按将图片用计算出的比例压缩,并加载至内存中使用
官网大图片加载教程(上面网址里的)对应代码就是:
1 /**
2 * 获取压缩后的图片
3 * @param res
4 * @param resId
5 * @param reqWidth 所需图片压缩尺寸最小宽度
6 * @param reqHeight 所需图片压缩尺寸最小高度
7 * @return
8 */
9 public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
10 int reqWidth, int reqHeight) {
11
12 // 首先不加载图片,仅获取图片尺寸
13 final BitmapFactory.Options options = new BitmapFactory.Options();
14 // 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息
15 options.inJustDecodeBounds = true;
16 // 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象
17 BitmapFactory.decodeResource(res, resId, options);
18
19 // 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4
20 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
21
22 // 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了
23 options. inJustDecodeBounds = false;
24 // 利用计算的比例值获取压缩后的图片对象
25 return BitmapFactory.decodeResource(res, resId, options);
26 }
设为true时去decode获取图片,只会加载像素宽高信息
设为false时decode则会完全加载图片
inSampleSize 压缩比例
比如原图200*300,如果值是2时会压缩成100*150; 是4则图片压缩成50*75
最好是2的幂数,比如2 4 8 16 .....
outHeight 图片原高度
outWidth 图片原宽度
其他参数自行研究,这里暂时只用到这几个
decodeSampledBitmapFromResource方法内的三段代码对应上面的三步流程
难点在于中间那步,压缩比例的计算,官网同样提供了个calculateInSampleSize方法
其中reqWidth和reqHeight是所需图片限定最小宽高值
1 /**
2 * 计算压缩比例值
3 * @param options 解析图片的配置信息
4 * @param reqWidth 所需图片压缩尺寸最小宽度
5 * @param reqHeight 所需图片压缩尺寸最小高度
6 * @return
7 */
8 public static int calculateInSampleSize(BitmapFactory.Options options,
9 int reqWidth, int reqHeight) {
10 // 保存图片原宽高值
11 final int height = options. outHeight;
12 final int width = options. outWidth;
13 // 初始化压缩比例为1
14 int inSampleSize = 1;
15
16 // 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统
17 if (height > reqHeight || width > reqWidth) {
18
19 final int halfHeight = height / 2;
20 final int halfWidth = width / 2;
21
22 // 压缩比例值每次循环两倍增加,
23 // 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止
24 while ((halfHeight / inSampleSize) >= reqHeight
25 && (halfWidth / inSampleSize) >= reqWidth) {
26 inSampleSize *= 2;
27 }
28 }
29
30 return inSampleSize;
31 }
官网的这个方法是: 将图片一半一半的压缩,直到压缩成成大于所需宽高数的那个最低值
大于~不是大于等于,所以就会出现我上面那种情况,我觉得方法不是太好= = 能满足压缩的需求,但是压缩的比例不够准确~
所以最好改成大于等于,如下(个人意见,仅供参考,在实际压缩中很少遇到恰巧等于的这个情况,所以>和>=差别也不大额~看我这扯扯淡就当对计算比例的逻辑加深个理解吧)
优化:
还是上面例子,如果限定了200*150,而原图是390*290会是个啥情况?
还是第一次while循环,390/2/1结果是195不满足>200的情况,结束循环,比例值为1,最后图片压缩成400*300
虽然压缩一次以后没有满足大于所需宽高,但是和所需宽高很接近啊!!!
能不能做一个获取压缩成最接近所需宽高数的比例值呢?
我也不知道= = 回头可以慢慢研究, 这个"接近"的定义比较模糊,不好掌握~
找了几个有名的图片加载开源框架发现也都没有这种处理- -不知道是这样设计是不需要呢,还是没啥用呢
*/
----------------------------------------------------------
以上,图片的像素大小已经做了缩放,但是图片的大小除了和像素有关,还和色彩样式有关
不同的样式决定了图片单个像素占的字节数
比如,图片默认的色彩样式为ARGB_8888,每个像素占4byte(字节)大小
参考资料:http://developer.android.com/reference/android/graphics/Bitmap.Config.html
可以看到一共有四种色彩样式
ALPHA_8 每个像素只要1字节~可惜只能代表透明度,没有颜色属性
ARGB_4444 每个像素要2字节~带透明度的颜色~可惜官方不推荐使用了
ARGB_8888 每个像素要4字节~带透明度的颜色, 默认色样
RGB_565 每个像素要2字节~不带透明度的颜色
默认为ARGB_8888,如果想丧心病狂的继续减少图片所占大小~不需要透明度参数的话,
那就可以把色彩样式设为RGB_565
设置方法是在BitmapFactory.decode..获取图片事例时
修改配置参数的inPreferredConfig 参数
----------------------------------------------------------
想亲自撸一撸试一试压缩图片了吧?
要注意点问题,如果用res包下图片测试的话,你会发现有图片尺寸有点混乱
那是因为在drawable-*dpi文件夹中的图片会根据对应对应的屏幕密度值不同自动进行一定的缩放,
比如放在drawable-hdpi里的图片,直接不经过压缩BitmapFactor.decode..出来,会发现bitmap的宽高值是原图的2/3,
测试的时候图片记得放在drawable包下(没有的话自己res下新建一个),否则你会被奇怪的宽高值弄凌乱的
具体变化原因参考源代码处理,或者网上搜搜看
还有就是BitmapFactory.decodeStream方法会偶尔解析图片失败(好像是安卓低版本的一个bug)
Android Bitmap 全面解析(一)加载大尺寸图片的更多相关文章
- Android Bitmap 全面解析(二)加载多张图片的缓存处理
一般少量图片是很少出现OOM异常的,除非单张图片过~大~ 那么就可以用教程一里面的方法了通常应用场景是listview列表加载多张图片,为了提高效率一般要缓存一部分图片,这样方便再次查看时能快速显示~ ...
- Android开发中如何解决加载大图片时内存溢出的问题
Android开发中如何解决加载大图片时内存溢出的问题 在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给 ...
- Android使用BitmapFactory.Options解决加载大图片内存溢出问题
由于Android对图片使用内存有限制,若是加载几兆的大图片便内存溢出.Bitmap会将图片的所有像素(即长x宽)加载到内存中,如果图片分辨率过大,会直接导致内存溢出(java.lang.OutOfM ...
- Android Bitmap 全面解析(四)图片处理效果对比 ...
对比对象: UIL Volley 官方教程中的方法(此系列教程一里介绍的,ImageLoader的处理方法和官方的差不多) -------------------------------------- ...
- 36、Android Bitmap 全面解析
Android Bitmap 全面解析(一)加载大尺寸图片 http://www.eoeandroid.com/thread-331669-1-1.html Android Bitmap 全面解析(二 ...
- Android(java)学习笔记236:多媒体之加载大图片到内存(Bitmap API)
1.Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度,然 ...
- Android(java)学习笔记179:多媒体之加载大图片到内存(Bitmap API)
1. Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度, ...
- 【Android Developers Training】 56. 更效率地加载大图片
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- Android简易实战教程--第二十八话《加载大图片》
Android系统以ARGB表示每个像素,所以每个像素占用4个字节,很容易内存溢出.假设手机内存比较小,而要去加载一张像素很高的图片的时候,就会因为内存不足导致崩溃.这种异常是无法捕获的 内存不足并不 ...
随机推荐
- 重新整理 .net core 实践篇——— filter[四十四]
前言 简单介绍一下filter 正文 filter 的种类,微软文档中写道: 每种筛选器类型都在筛选器管道中的不同阶段执行: 授权筛选器最先运行,用于确定是否已针对请求为用户授权. 如果请求未获授权, ...
- loadrunner12自带的机票预订服务,解决httpd: Could not reliably determine the server's fully qualified domain name 问题
遇到以上问题是在启动loadrunner12自带的机票预订服务器情况下遇到的,错误提示如下图: 解决方案: 编辑httpd.conf 文件,加入一句 ServerName localhost:1080 ...
- layui表格-template模板的三种用法
问题情境: layui中将数据库数据通过layui table渲染到前端表格,非常简单,但是如果数据库存储的信息不能被直接展示,项目中该页面有好几个这样的字段,会员类型,支付类型,会员时长还有平台类型 ...
- GitHub 12个实用技巧-从projiect项目管理、代码链接到博客wiki全过程
1 在GitHub.com上编辑代码 2 粘贴图片 3 美化代码 4 在PRs中巧妙关闭issues 5 链接到评论 6 链接到代码 7 灵活使用GitHub地址栏 8 创建复选框列表 9 在GitH ...
- Mac 下 Nginx 配置使用
安装 homebrew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/m ...
- [Vue]浅谈Vue3组合式API带来的好处以及选项API的坏处
前言 如果是经验不够多的同志在学习Vue的时候,在最开始会接触到Vue传统的方式(选项式API),后边会接触到Vue3的新方式 -- 组合式API.相信会有不少同志会陷入迷茫,因为我第一次听到新的名词 ...
- 基于linux与线程池实现文件管理
项目要求 1.基本 用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件:实现复制到指定文件夹的全部文件夹. 2.扩充功能 显示进度条:拷贝耗时统计:类似linux的tree,不能直接用system ...
- [bzoj4553]序列
记第i个位置有三个属性:1.ai表示原来的值:2.bi表示变成最大的值:3.ci表示变成最小的值.那么对于如果i在j的前面,那么必然有:$ai\le cj$且$bi\le aj$,那么令f[i]表示以 ...
- [bzoj1109]堆积木
用f[i]表示前i个数,i必须被贡献的答案,考虑转移,枚举下一个被贡献的数j,那么j需要满足:1.$j<i$:2.$a[j]<a[i]$:3.$a[i]-(i-j+1)\le a[j]$, ...
- 【Tool】IntelliJ IDEA 使用技巧
IntelliJ IDEA 使用技巧 2019-11-06 20:51:43 by冲冲 1.快捷键 Ctrl+w //括出相关范围 Ctrl+shift+f //按照代码段在全局搜索 Ctrl+f ...