【Bitmap】—— 基础知识


 【Bitmap能够解决的问题】

1、我们知道一般我们使用图片的话,都是使用保存在res/drawable/文件夹下的图片资源,

比如ImageView , 在布局文件中是 <ImageView  android:src = "@drawable/picture">

如果在Java代码中则是 setImageResource(int resId)

2、那就会出现一个问题,如果我们想要使用SD卡存储器中图片文件作为ImageView的资源,这时候该怎么办呢?要完成这个问题,需要以下几步:

①将SD卡中的图片文件解析成Bitmap对象

②调用ImageView的 setImageBitmap (Bitmap m) 方法,为ImageView加载这个Bitmap对象

3、除此之外,将一张图片转换成Bitmap对象之后,就能够非常方便的对Bitmap中的图片进行变换,如:剪裁、旋转、缩放等变幻从而创建出新的Bitmap对象

 

【Bitmap基础】

1、Bitmap和BitmapDrawable之间的转化方法:

Bitmap代表一张位图,BitmapDrawable 里封装的图片就是一个Bitmap对象。开发者为了将一个Bitmap对象包装成一个BitmapDrawable对象,可以调用BitmapDrawable的构造方法:

//把一个Bitmap对象包装成BitmapDrawable
BitmapDrawable drawable = new BitmapDrawable(bitmap) ;

如果想要取出BitmapDrawable中的Bitmap对象的话,只需要调用BitmapDrawable的getBitmap()方法

Bitmap bitmap = drawable.getBitmap() ;

这样的话,我们就能够进行Bitmap和Drawable之间的转化

 

2、如何通过已有的Bitmap对象创建新的Bitmap对象

非常的方便就是使用Bitmap的下面的几个静态方法来创建:

 

createBitmap(Bitmap source ,int x, int y , int width , int height)

从原位图Bitmap指定的坐标点(x , y 参数)开始,从中“挖取” 宽width、 高height 的一块出来,创建新的Bitmap对象

createBitmap(Bitmap source , int x, int y , int width , int height , Matrix m , boolean filter)

createScaledBitmap(Bitmap src  , int dstWidth , int  dstHeight , boolean) 对src位图缩放成宽dstWidth 、高dstHeight的新位图

当然还有其他的方法,可以查阅文档

3、如何将不同的数据源解析成Bitmap对象

需要借助于BitmapFactory这个工具类中的静态方法

 

//从指定的字节数组的offset位置开始,将长度为length的字节数组数据解析成Bitmap对象
        BitmapFactory.decodeByteArray(byte [ ] data , int offset, int length);
        
        //从pathName指定的文件中解析出Bitmap对象
        BitmapFactory.decodeFile(String pathName) ;
        
        //从FileDescriptor对应的文件中解析成Bitmap对象
        BitmapFactory.decodeFileDescriptor(FileDescriptor fd) ;
        
        //根据给定的资源ID,从指定的资源中解析出Bitmap对象
        BitmapFactory.decodeResource(Resuorces, int id)
        
        //用于从指定的打开的图片文件的输入流中解析出Bitmap对象
        BitmapFactory.decodeStream(InputStream is) ;

 

4、Bitmap的回收问题 

由于手机的内存比较小,如果不停的去解析和创建Bitmap对象,可能由于由于前面所创建的Bitmap所占用的内存还没有被回收,而导致程序运行时引发OutOfMemory错误

Android为Bitmap提供了两个方法,用于检测当前的Bitmap对象是否已经被回收,以及强制回收当前的Bitmap对象:

//返回Bitmap对象是否已经被回收
boolean isRecycled()
        
//强制回收当前的Bitmap对象
void recycle()

 

【Bitmap实例】

我们要使用ViewPager来实现一个SD卡照片查看器:

先看看效果: 

android 获取资源xml android 获取资源图片bitmap_android

完整显示页面

android 获取资源xml android 获取资源图片bitmap_List_02

手指滑动过渡页面

 

1 package com.penglee.imageviewer_test;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.util.ArrayList;
 6 import java.util.List;
 7 
 8 import android.app.Activity;
 9 import android.graphics.BitmapFactory;
10 import android.os.Bundle;
11 import android.os.Environment;
12 import android.support.v4.view.ViewPager;
13 import android.widget.ImageView;
14 import android.widget.ImageView.ScaleType;
15 import android.widget.LinearLayout;
16 import android.widget.Toast;
17 
18 public class MainActivity extends Activity {
19     
20     static final String FOLDER_PATH = "/Picture/"; //SD卡中存有图片文件的文件夹
21     File [ ] fileList ; //保存指定文件夹下的所有文件
22     
23     ViewPager viewPager ; 
24 
25     @Override
26     protected void onCreate(Bundle savedInstanceState) {
27         super.onCreate(savedInstanceState);
28         setContentView(R.layout.activity_main);
29         
30         viewPager = (ViewPager)findViewById(R.id.viewPager);
31         
32         //判定手机中是否插入了SD卡,并且本应用程序有读取权限
33         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
34                 //获取SD卡的目录
35                 File sdCardDir = Environment.getExternalStorageDirectory() ;           
36                  try {
37                      
38                     File targetFolder = new File(sdCardDir.getCanonicalFile()+FOLDER_PATH);
39                     if(!targetFolder.exists())  
40                     {
41                         Toast.makeText(MainActivity.this, "当前目录不存在", Toast.LENGTH_SHORT).show();
42                         return ;  //一旦执行了return ,那么onCreate方法中位于该return下面的代码就不会再执行了
43                     }
44                     
45                     fileList =targetFolder.listFiles() ; 
46                     
47                     if(fileList.length == 0) {        
48                         Toast.makeText(MainActivity.this, "当前目录下不存在文件", Toast.LENGTH_SHORT).show();
49                         return ;//一旦执行了return ,那么onCreate方法中位于该return下面的代码就不会再执行了
50                     }
51                     
52                      } catch (IOException e) {
53                           e.printStackTrace();
54                      }
55         }
56         
57         List<ImageView> pictures = new ArrayList<ImageView>() ;
58         
59         LinearLayout.LayoutParams mParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,  
60                                               LinearLayout.LayoutParams.MATCH_PARENT);
61         for(int i =0 ; i < fileList.length ; i++){
62             if(fileList[i].getName().endsWith(".png")||fileList[i].getName().endsWith(".jpg")){
63                 ImageView imageView = new ImageView(MainActivity.this);
64                 imageView.setLayoutParams(mParams);
65                 imageView.setScaleType(ScaleType.FIT_CENTER);
66                 //关于如何将SD卡中的图片文件转化成Bitmap对象,从而能够让ImageView使用,参见Bitmap相关博文
67                 imageView.setImageBitmap(BitmapFactory.decodeFile(fileList[i].getAbsolutePath()));
68                 pictures.add(imageView);
69             }
70         }
71        
72         //创建PictureAdapter
73         PictureAdapter pictureAdapter = new PictureAdapter(pictures);
74         //为ViewPager设置Adapter
75         viewPager.setAdapter(pictureAdapter);
76     }
77 
78 }

 

 

1 package com.penglee.imageviewer_test;
 2 
 3 import java.util.List;
 4 
 5 import android.os.Parcelable;
 6 import android.support.v4.view.PagerAdapter;
 7 import android.view.View;
 8 import android.widget.ImageView;
 9 import android.support.v4.view.ViewPager ;
10 
11 public class PictureAdapter extends PagerAdapter{
12     
13             private List<ImageView> pictureViews ;
14             
15             public PictureAdapter(List<ImageView> list){
16                 this.pictureViews = list ;
17             }
18 
19             //销毁arg1位置的界面  
20              @Override  
21              public void destroyItem(View arg0, int arg1, Object arg2) {  
22                  ((ViewPager) arg0).removeView(pictureViews.get(arg1));       
23              }  
24            
25              @Override  
26              public void finishUpdate(View arg0) {  
27                  // TODO Auto-generated method stub         
28              }  
29            
30              //获得当前界面数  
31              @Override  
32              public int getCount() {  
33                  if (pictureViews != null)  
34                  {  
35                     return pictureViews.size();  
36                  }  
37                  return 0;  
38              }  
39                
40           
41              //初始化arg1位置的界面  
42              @Override  
43              public Object instantiateItem(View arg0, int arg1) {  
44                    
45                  ((ViewPager) arg0).addView(pictureViews.get(arg1), 0);  
46                  return pictureViews.get(arg1);  
47              }  
48            
49              //判断是否由对象生成界面  
50              @Override  
51              public boolean isViewFromObject(View arg0, Object arg1) {  
52                  return (arg0 == arg1);  
53              }  
54            
55              @Override  
56              public void restoreState(Parcelable arg0, ClassLoader arg1) {  
57                  // TODO Auto-generated method stub  
58                    
59              }  
60            
61              @Override  
62             public Parcelable saveState() {  
63                  // TODO Auto-generated method stub  
64                  return null;  
65              }  
66            
67              @Override  
68              public void startUpdate(View arg0) {  
69                  // TODO Auto-generated method stub  
70                    
71              }  
72 }

 

1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context="com.penglee.imageviewer_test.MainActivity" >
 6 
 7      <!-- 加载ViewPaper -->
 8      <android.support.v4.view.ViewPager
 9         android:id="@+id/viewPager"
10         android:layout_width="match_parent"
11         android:layout_height="match_parent">
12          
13     </android.support.v4.view.ViewPager>
14 
15 
16 </RelativeLayout>