android 应用开发对大图片的处理
一,下载
android下载大图片(例如微博长图片)会出现OOM down掉问题
解决这个问题的办法是下载图片时先得到图片的宽度和高度,如果超出规定限制则对图片进行缩放
关键参数
1. BitmapFactory.Options.inJustDecodeBounds
inJustDecodeBounds:boolean类型,如果设为true,则进行辩解判断,并不申请bitmap内存
2.BitmapFactory.Options.inJustDecodeBounds.outWidth和outHeight
如果inJustDecodeBounds为true,则可得到outWidth和outHeight的值,根据这个两个值决定是否进行缩放
eg
public static Drawable loadImage(String url){ URL m; InputStream is = null; try { m = new URL(url); is = (InputStream) m.getContent(); BufferedInputStream bis = new BufferedInputStream(is); //标记其实位置,供reset参考 bis.mark(0); BitmapFactory.Options opts = new BitmapFactory.Options(); //true,只是读图片大小,不申请bitmap内存 opts.inJustDecodeBounds = true; BitmapFactory.decodeStream(bis, null, opts); Log.v("AsyncImageLoader", "width="+opts.outWidth+"; height="+opts.outHeight); int size = (opts.outWidth * opts.outHeight); if( size > 1024*1024*4){ int zoomRate = 2; //zommRate缩放比,根据情况自行设定,如果为2则缩放为原来的1/2,如果为1不缩放 if(zoomRate <= 0) zoomRate = 1; opts.inSampleSize = zoomRate; Log.v("AsyncImageLoader", "图片过大,被缩放 1/"+zoomRate); } //设为false,这次不是预读取图片大小,而是返回申请内存,bitmap数据 opts.inJustDecodeBounds = false; //缓冲输入流定位至头部,mark() bis.reset(); Bitmap bm = BitmapFactory.decodeStream(bis, null, opts); is.close(); bis.close(); return (bm == null) ? null : new BitmapDrawable(bm); } catch (MalformedURLException e1) { Log.v("AsyncImageLoader", "MalformedURLException"); e1.printStackTrace(); } catch (IOException e) { Log.v("AsyncImageLoader", "IOException"); e.printStackTrace(); } return null; }
二、加载
Android应用开发中我们会经常用到图片处理的技术
移动开发中,内存资源很宝贵,而且对加载图片内存空间也有限制;所以我们会在加载图片对图片进行相应的处理,有时为了提高响应速度,增强用户体验, 我们在加载大图片时会先加载图片的缩略图、如后加载原图,所以我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用BitmapFactory的 decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几 分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。
然而,如果我们想取固定大小的缩略图就比较困难了,比如,我们想将不同大小的图片去出来的缩略图高度都为200px,而且要保证图片不失真,那怎么 办?我们总不能将原始图片加载到内存中再进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止 100K?
经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于明白是什么意思了,SDK中的E文是这么说的
If set to true, the decoder will return null (no bitmap), but the out...
fields will still be set, allowing the caller to query the bitmap
without having to allocate the memory for its pixels.
意思就是说如果该值设为true那么将不返回实际的bitmap不给其分配内存空间而里面只包括一些解码边界信息即图片大小信息,那么相应的方法也就出来
了,通过设置inJustDecodeBounds为true,获取到outHeight(图片原始高度)和
outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),然后就可以取图片了,这里要注意的是,inSampleSize
可能小于0,必须做判断。
具体代码如下:
FrameLayout fr=(FrameLayout)findViewById(R.id.FrameLayout01);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
// 获取这个图片的宽和高
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/test.jpg", options); //此时返回bm为空
options.inJustDecodeBounds = false;
//计算缩放比
int be = (int)(options.outHeight / (float)200);
if (be <= 0)
be = 1;
options.inSampleSize = be;
//重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦
bitmap=BitmapFactory.decodeFile("/sdcard/test.jpg",options);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
System.out.println(w+" "+h);
ImageView iv=new ImageView(this);
iv.setImageBitmap(bitmap);
这样我们就可以读取较大的图片就会避免内存溢出了。如果你想把压缩后的图片保存在Sdcard上的话就很简单了:
File file=new File("/sdcard/feng.png");
try {
FileOutputStream out=new FileOutputStream(file);
if(bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)){
out.flush();
out.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ok,这样就把图片保存在/sdcard/feng.png这个文件里面了
android 应用开发对大图片的处理的更多相关文章
- Android应用开发学习之图片切换器
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 如果我们要实现类似Windows的照片查看器切换上一张下一张照片的效果,可以使用图片切换器ImageSwitcher ...
- 微信android手机中点击大图片会自动放大图片
自己使用的是微信Android客户端,使用img标签的src属性将图片设置好了以后,在微信中调试,点击图片竟然放大,自己没写放大图片的方法,也没有调用wx.previewImage()方法,最后查找, ...
- Android(java)学习笔记236:多媒体之加载大图片到内存(Bitmap API)
1.Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度,然 ...
- Android调用系统相机、自己定义相机、处理大图片
Android调用系统相机和自己定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,而且因为涉及到要把拍到的照片显示出来,该样例也会涉及到Android载入大图片时候的处 ...
- Android(java)学习笔记179:多媒体之加载大图片到内存(Bitmap API)
1. Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度, ...
- Android开发中如何解决加载大图片时内存溢出的问题
Android开发中如何解决加载大图片时内存溢出的问题 在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给 ...
- Android Camera开发系列(上)——Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片
Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 最近也是在搞个破相机,兼容性那叫一个不忍直视啊,于是自己翻阅了一些基本的资料,自己实现了一 ...
- Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能
Android Camera开发系列(下)--自定义Camera实现拍照查看图片等功能 Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 上 ...
- Android应用开发中三种常见的图片压缩方法
Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩). 一.质量压缩法 private Bitmap com ...
随机推荐
- URL & webkitURL
base64带来的坑 在web中想要是实现图片在线预览的方式有几种 1.先上传 2.使用FileReader对象 3.URL.createObjectURL(file|blob) base64 能将图 ...
- struts2 <s:iterator> 遍历方法
1.MapAction.java import java.util.ArrayList; import java.util.HashMap; import java.util.List; ...
- UVA 140 Bandwidth
题意: 给出一个n个节点的图G,和一个节点的排列,定义节点i的带宽为i和相邻节点在排列中的最远距离,而所有带宽的最大值就是图的带宽,求让图的带宽最小的排列. 分析: 列出所有可能的排列,记录当前找到的 ...
- Android 贝塞尔曲线
博客图片备份位置:
- join函数——Gevent源码分析
在使用gevent框架的时候,我们经常会使用join函数,如下: def test1(id): print(id) gevent.sleep(0) print(id, 'is done!') t = ...
- std::map的insert和下标[]访问
在map中插入元素 改变map中的条目非常简单,因为map类已经对[]操作符进行了重载 enumMap[1] = "One";enumMap[2] = "Two" ...
- 获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点
//获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点 $(function () { $('.easyui-tree') ...
- Node.js HTTP 使用详解
对于初学者有没有发觉在查看Node.js官方API的时候非常简单,只有几个洋文描述两下子,没了,我第一次一口气看完所以API后,对于第一个示例都有些懵,特别是参数里的request和response, ...
- 强化一下,QDialog有专门的exec函数和finished信号,QWidget都没有
http://blog.csdn.net/dbzhang800/article/details/6300519
- WPF中实现先登录后启动主程序的方法
原文:WPF中实现先登录后启动主程序的方法 我觉得先登录后启动应用主程序是一个很经典的问题,基本上如果要写一个应用程序都会用到这个的小环节.我在这个问题上挣扎了大半天才找到解决方案,我的实现方法我觉得 ...