Android笔记二十七.Bitmap之简易图片查看器

 转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空)
为了增强用户之间的交互,Android系统中提供了一些API和部件给我们开发美观有趣的应用。比如Android系统提供了ImageView来显示静态图片、AnimationDrawble来开发逐帧动画以及通过Animation对普通图片使用不减动画等。另外,Android应用中的图片不仅包括*.png、*.jpg、*.gif等格式的位图,也包括使用XML资源文件定义的各种Drawable对象。关于Drawable对象的使用,主要有以下几个方面:
(1)@drawable/file_name:在XML资源文件中通过@drawable/file_name来访问该Drawable对象;
(2)R.drawable.file_name:在Java代码中通过该图片资源的R清单文件中的索引项R.drawable.file_name访问该Drawable对象。
(3)Resources.getDrawable(int id):由于R.drawable.file_name是一个int类型的常量,其只代表Drawable对象的ID,如果在Java程序中需要获得实际的Drawable对象,则可调用该方法来获取。
一、图片处理API
*Bitmap代表一张位图;
*BitmapDrawable:用于封装图片,即封装的图片就是一个Bitmap对象;
*BitmapFactory:为一个工具类,用于提供大量的方法,这些方法可用于从不同的数据源来解析、创建一个Bitmap对象                                        
1.Bitmap类
      代表一张位图(即普通的*.png、*.jpg、*.gif等格式图片),Bitmap类负责管理和转换原始位图图形,其常用方法有:
(1)从其他途径创建一个Bitmap对象
>static Bitmap createBitmap(Bitmap source,int x,int y,int width,int height):从源位图source的 指定坐标点(给定x、y)开始,从中"挖取"宽width、高height的一块处理用于创建新的Bitmap对象。
>static Bitmap createScaledBitmap(Bitmap src,iint dstWidth,int dstHeight,boolean filter):对源位图src进行缩放,缩放成宽 dstWidth、高dstHeight的新位图。
>static Bitmap createBitmap(int width,int height,Bitmap.Config config):创建一个宽width、高height的新位图,其中Bitmap.Config为位图的配置是Bitmap的嵌入类用于描述像素是怎样存储的(ALPHA_8、ARGB_8888 、RGB_565 )
>static Bitmap createBitmap(Bitmap source,int x,int y,int width,int height,Matrix m,boolean filter):从源位图source的指定坐标点(给定x、y)开始,从中"挖取"宽width、高height的一块位图来创建新的Bitmap对象,并按Matrix指定的规则进行变换。
(2)获取位图的宽度、高度大小
>final int getHeight() :返回位图的高度
>final int getWidth() :返回位图的宽度
>int getScaledHeight(int targetDensity) :返回被缩放位图的高度
>int getScaledWidth(int targetDensity) :返回被缩放位图的宽度
(3)判断Bitmap对象是否被收回
>final boolean isRecycled() :返回该Bitmap对象是否已被回收
>void recycle() :强制一个Bitmap对象立即回收自己
注释:这里提到Bitmap对象的回收问题,主要是因为大部分时候,我们只要把图片放在/res/drawable-mdpi目录下,就可以在程序中通过图片对象的ID来获取封装该图片的Drawable对象。但由于手机系统的内存比较小,如果系统不停地去解析、创建Bitmap对象,可能由于前面创建Bitmap所占用的内存还没有回收而导致程序运行时引发"内存溢出"错误。

2.BitmapDrawable类
    BitmapDrawable类用于包装一个位图,并且该Drawable可被平铺、拉升、对齐等操作。我们可以从一个文件路径、一个输入流、XML或者Bitmap对象来创建一个BitmapDrawable对象。
(1)构造方法
>BitmapDrawable(Bitmap bitmap)
>BitmapDrawable(Resources res, Bitmap bitmap)
(2)常用方法
>final Bitmap getBitmap():获取该BitmapDrawable对象对应的Bitmap对象
>final Paint getPaint() :获取渲染该drawable的paint对象
>void setAlpha(int alpha) :为drawable对象指定透明度
注释:我们可以使用"BitmapDrawable drawable = new BitemapDrawable(bitmap);"语句把一个Bitmao对象包装成BitmapDrawable对象;通过"Bitmap bitmap = drawable.getBitmap()"语句来获取BitmapDrawable所包装的Bitmap对象。

3.BitmapFactory类
   BitmapFactory类 为一个工具类,提供大量的方法可用于从不同的数据源来解析、创建一个Bitmap对象。比如Android应用需要访问其他存储路径(SD卡中)里的图片,都需要借助于BitmapFactory来解析和创建一个Bitmap对象
(1)构造方法:BitmapFactory()
(2)常用方法:
>static Bitmap  decodeByteArray(byte[] data, int offset, int length) :从指定字节数组的offset位置开始,将长度为length的字节数据解析成Bitmap对象 
>static Bitmap  decodeFile(String pathName) :从pathName指定的文件中解析、创建Bitmap对象 
>static Bitmap  decodeFileDescriptor(FileDescriptor fd):从FileDescriptor(文件描述符)对应的文件中解析、创建Bitmap对象 
>static Bitmap  decodeResource(Resources res, int id) :根据给定的资源ID从指定资源中解析、创建Bitmap对象 
>static Bitmap  decodeStream(InputStream is):从指定输入流中解析、创建Bitmap对象 

二、简易图片查看器开发思路


    本应用主要是实现查看/res/assets目录下所有的图片,对于图片的替换主要是调用ImageView的setImageBitmap(Bitmap bitmap)方法。 所以,我们最终的目的就是要获得切换图片对应的Bitmap对象。具体步骤:(1)首先需要获取assets所有文件列表("AssetManager assets=getAssets();String[]  assetsImages = assets.list("");然后,(2)获取并打开字符串数数组中一张图片资源输入流(InputStream stream = assets.open(assetsImages[currentImage])
(3) 调用Bitfactory.decodeStream(InputStream stream)方法获取该位图的Bitmap对象,最后在调用ImageView的setImageBitmap(Bitmap bitmap)方法实现切换图片效果。
注意:由于图片的切换,系统会不停地去解析、创建Bitmap对象,所以,为了避免手机内存"溢出"情况,在切换图片之前需要判定当前Bitmap是否被收回,否者需要强制收回该图片。
BitmapDrawable bitmapDrawable = (BitmapDrawable)imageView.getDrawable();    //获取当前图片的BitmapDrawable对象
if(bitmapDrawable != null && !bitmapDrawable.getBitmap().isRecycled())                //通过BitmapDrawable对象获得对应的Bitmap对象及其方法
{
     bitmapDrawable.getBitmap().recycle();
}

三、源码实现
实现:开发一个查看/assets/目录下图片的图片查看器。
BitmapTest.java
<span style="font-size:18px;">package com.example.bitmaptest;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.res.AssetManager;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class BitmapTest extends Activity {
 private int currentImage=0;
 String[] assetsImages;
 ImageView imageView;
 AssetManager assets; // asset资源管理引用变量
 InputStream stream=null;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.mian);
  imageView = (ImageView) findViewById(R.id.imageview);
  // 1.获取/res/assets目录下文件列表
  try {
   assets = getAssets(); // 获取asset资源管理对象
   assetsImages = assets.list(""); // 获取assets目录下的所有文件名存放至String数组中
   stream=assets.open(assetsImages[currentImage]);	//ImageView设置为Assets目录下的第一张图片
   imageView.setImageBitmap(BitmapFactory.decodeStream(stream));
  } catch (IOException e) {
   e.printStackTrace();
  }
  // 2.为btn按钮注册事件监听器,实现循环图片切换功能
  Button btn = (Button) findViewById(R.id.button);
  btn.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    //a.累加数组下标currentImage
    if(!assetsImages[currentImage].endsWith("*.png") && !assetsImages[currentImage].endsWith("*.jpg") &&!assetsImages[currentImage].endsWith("*.gif"))
    {
     currentImage++;
     if(currentImage==assetsImages.length-3)	//如果发现数组越界,重置currentImage
     {
      currentImage=0;
     }
    }
    //b.打开指定资源的输入流
    InputStream stream = null;
    try {
     stream=assets.open(assetsImages[currentImage]);
    } catch (IOException e) {
     e.printStackTrace();
    }
    //c.获取当前图片的BitmapDrawable对象
    BitmapDrawable bitmapDrawable = (BitmapDrawable)imageView.getDrawable();
    if(bitmapDrawable!=null && !bitmapDrawable.getBitmap().isRecycled())
    {
        bitmapDrawable.getBitmap().recycle();
    }
    imageView.setImageBitmap(BitmapFactory.decodeStream(stream));
   }
  });
 }
}</span>
效果演示:
技术分享
技术分享

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。