资源描述
大图片之缩放加载
在上一个文档“图片加载之OOM”中,我们论述了Android下加载大图片的措施,下面我们就一个详细的DEMO来实现大图片的加载。详细步骤如下:
1. 新建工程
【File】à【new】à【Android Application Project】命名为:02_缩放加载大图片到内存
2. 编写布局
依照需求编写布局文献,效果如图1-1所示:
图1-1所示
图1-1对应的xml布局页面如例1-1:
例1-1
<RelativeLayout xmlns:android="
xmlns:tools="
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<Button
android:onClick="loadImage"
android:layout_width="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_height="wrap_content"
android:text="加载图片" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/iv"
/>
</RelativeLayout>
由例1-1可知:当点击按钮“加载图片”时,便执行loadImage措施从SD卡中读取图片数据并将该图片的缩略图布署在ImageView控件上。
3. 手机的辨别率
在获取该图片的缩略图时,我们需要懂得这个手机屏幕的宽和高。怎样获取屏幕的高度和宽度?详细代码如例1-2所示
例1-2
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
// 手机屏幕的辨别率
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
// 该措施已通过时,不过考虑版本的兼容我们还是应当选择这个措施
screenWidth = display.getWidth();// 返回值是int类型的
screenHeight = display.getHeight();
}
例1-2可知:getSystemService获取系统对手机屏幕的服务对象WindowManager,然后得到窗口管理器WindowManager的Display对象,最后通过该对象的get措施得到这个屏幕的高度和宽度。
4. 图片的辨别率
手机内存中表示图片的方式是以位图的形式将图片加载到内存中。为了防止OOM,我们选择内存加载该图片的缩略图。要得到该图片的缩略图,我们需要懂得这个图片自身的辨别率。下面是获取图片辨别率的详细措施。
类BitmapFactory的作用是从各个起源创建位图对象,这些起源包括文献,数据流,字节数组。本例中我们读指定文献下图片的位图,参考API文档,在读取指定途径下的文献数据流时有如下两种措施,如图1-2所示:
图1-2所示
从图1-2可知:若指定途径下图片解析成功,则这两个措施返回的都是一个Bitmap;当解析失败则返回的都是null。对于第一个措施,若第二个参数Options不为空,则还会返回指定途径下图片的其他信息如图片大小。我们发觉:这两个措施都会去解析指定途径下的图片,都会去申请内存空间。而我们所需要的仅仅是这个图片的属性值(高度和宽度),并不想在内存中加载这个图片。那么,怎样做既能得到图片的属性值又不在内存中加载这个图片呢?措施如下例1-3所示:
例1-3
public void loadImage(View view) {
Options opts = new Options();
// 不去直接解析这个位图,返回的是NUll 只是获取这个位图的 文献信息
opts.inJustDecodeBounds=true;
BitmapFactory.decodeFile("mnt/sdcard/vl.jpg", opts);
int picHeight =opts.outHeight;
int picWidth =opts.outWidth;
System.out.println("屏幕的高度:"+screenWidth+"~"+screenHeight);
System.out.println("屏幕的宽度:"+picWidth+"~"+picHeight);
}
例1-3通过opts.inJustDecodeBounds=true便可达只到读取图片属性的目标,下面我们对这个字段进行了解,参考文档如图1-3。
图1-3所示
当设置inJustDecodeBounds的值为true时,解析器将不会去解析指定途径下的图片,返回值是null。不过,我们却允许得到图片的属性值而无需给这个图片分派任何内存。当然,当我们设置inJustDecodeBounds的值为false时,也能够得到这个指定途径下的位图。
5. 计算缩略比
我们已经得到了手机屏幕的辨别率和图片的辨别率,接下来就是计算图片的缩略百分比了,然后将原图片按照这个缩略百分比进行缩放,最后再把缩放之后的图片加载到内存中。怎样计算缩略比?
计算缩略比的算法类似于我们数学概率上的抽样调查。Android中,我们先分别计算出图片的高和宽与手机屏幕高和宽的百分比值(假设分别为dy和dx),然后比较这个两个百分比值的大小,我们会选择值大者为这个图片的缩放比。详细代码如例1-4
例1-4
public void loadImage(View view) {
...........
int scale =1;
int dy = picHeight/screenHeight;//竖值方向的缩放比
int dx = picWidth/screenWidth;//水平方向的缩放比
if(dy>dx && dx>1){
scale=dy;
}
//对于这两个缩放比相同的处理
if(dx>=dy && dy>1){
scale=dx;
}
System.out.println("缩放百分比为:"+scale);
}
6. 加载缩放图片到内存
得到图片的缩放比之后,我们就能够先得到这个图片的缩放图啦。那么,怎样指定缩放比,得到这个图片的缩放图呢?代码如例1-5所示:
例1-5
public void loadImage(View view) {
............
System.out.println("缩放百分比为:"+scale);
opts.inSampleSize=scale;//指定压缩比
opts.inJustDecodeBounds=false; //为false时,才能得到这个图片的位图
Bitmap bitmap = BitmapFactory.decodeFile("mnt/sdcard/vl.jpg", opts);
iv.setImageBitmap(bitmap);
}
例1-1通过opts.inSampleSize=scale来指定图片的压缩比,查考文档对这个字段简介如图1-4所示:
图1-4所示
从图1-4可知:通过inSampleSize的值来指定缩放的百分比,当该值不小于1时,解析器将在原图片的基础上返回一个较小的位图从而达成节约内存的目标。
运行程序,logcat打印如图1-5所示:
图1-5所示
当点击按钮时,加载缩略图,效果如图1-6所示:
图1-6所示
展开阅读全文