Android Bitmap Api总结和使用方法

在学习Bitmap之前先学习一下Bitmap是怎么创建在,Bitmap的构造方法都是私有的,所以无法直接调用Bitmap的构造方法。我们只能通过BitmapFactory类和Bitmap.createBitmap来创建Bitmap。所以,我们要先了解BitmapFactory

BitmapFactory API总结
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//BitmapFactory Android4.4 API总结 2015年5月19日

//BitmapFactory 选项
public  static  class Options {
     public Options(){
        inDither = false;
        inScaled = true;
    }
     public Bitmap inBitmap;
     public  boolean inMutable;
     public  boolean inJustDecodeBounds;   //true时,只获取宽高
     public  int inSampleSize;             //缩放倍数,压缩图片内存大小 
     public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
     public  boolean inDither;
     public  int inDensity;
     public  int inTargetDensity;
     public  int inScreenDensity;
     public  boolean inScaled;
     public  boolean inPurgeable;
     public  boolean inInputShareable;
     public  boolean inPreferQualityOverSpeed;
     public  int outWidth;         //inJustDecodeBounds=true时,输出图片宽
     public  int outHeight;        //inJustDecodeBounds=true时,输出图片高
     public  String outMimeType;
     public  byte[] inTempStorage;
     private  native  void requestCancel();
     public  boolean mCancel;
     public  void requestCancelDecode(){
        mCancel = true;
        requestCancel();
    }
}

//通过文件路径创建Bitmap    
static Bitmap decodeFile( String pathName, Options opts);
static Bitmap decodeFile( String pathName);
//通过resources id创建Bitmap
//value: 一些图片值,如density等
static Bitmap decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad, Options opts);
static Bitmap decodeResource(Resources res,  int id, Options opts);
static Bitmap decodeResource(Resources res,  int id);
//通过二进制创建Bitmap
//offset: 位置偏移
//length:data数组的读取长度
static Bitmap decodeByteArray( byte[] data,  int offset,  int length, Options opts);
static Bitmap decodeByteArray( byte[] data,  int offset,  int length);
//通过流文件创建Bitmap
static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts);
static Bitmap decodeStream(InputStream is);
//通过流文件描述符创建Bitmap
static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts);
static Bitmap decodeFileDescriptor(FileDescriptor fd);

BitmapFactory API使用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

//decodeResource 使用方法
Bitmap rawBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.haha);

//decodeFile 使用方法
String SDCarePath = Environment.getExternalStorageDirectory().toString();
String filePath = SDCarePath +  "/" +  "haha.jpg";
Bitmap rawBitmap1 = BitmapFactory.decodeFile(filePath, null);

//decodeStream 使用方法
InputStream is;
is = context.getResources().openRawResource(R.drawable.frog);
mBitmap2 = BitmapFactory.decodeStream(is);

//decodeByteArray 使用方法
ByteArrayOutputStream os =  new ByteArrayOutputStream();

//(压缩格式, 压缩质量 0-100, 输出流)
src.compress(format, quality, os);
byte[] array = os.toByteArray();
return BitmapFactory.decodeByteArray(array,  0, array.length);

Bitmap createBitmap API总结
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//从原位图src复制出一个新的位图,和原始位图相同
public  static Bitmap createBitmap (Bitmap src)
//这个函数根据颜色数组来创建位图,注意:颜色数组的长度>=width*height
//此函数创建位图的过程可以简单概括为为:以width和height创建空位图,然后用指定的颜色数组colors来从左到右从上至下一次填充颜色。
//config是一个枚举,可以用它来指定位图“质量”。
public  static Bitmap createBitmap ( int[] colors,  int width,  int height, Bitmap.Config config) 
//offset      写入到pixels[]中的第一个像素索引值 
//stride      pixels[]中的行间距个数值(必须大于等于位图宽度) 
public  static Bitmap createBitmap ( int[] colors,  int offset,  int stride,  int width,  int height, Bitmap.Config config)
/*
从原始位图剪切图像,这是一种高级的方式。可以用Matrix(矩阵)来实现旋转等高级方式截图
参数说明:
  Bitmap source:要从中截图的原始位图
  int x:    起始x坐标
  int y:    起始y坐标
    int width:  要截的图的宽度
    int height:要截的图的宽度
Bitmap.Config  config:一个枚举类型的配置,可以定义截到的新位图的质量
返回值:返回一个剪切好的Bitmap
 */

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

//根据参数创建新位图
public  static Bitmap createBitmap ( int width,  int height, Bitmap.Config config)
//简单的剪切图像的方法,可以参考createBitmap
public  static Bitmap createBitmap (Bitmap source,  int x,  int y,  int width,  int height) 

Bitmap createBitmap及Bitmap. Config作用方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
private  static  final  int WIDTH =  50;
private  static  final  int HEIGHT =  50;
private  static  final  int STRIDE =  64;    // must be >= WIDTH
private Bitmap[] mBitmaps;
private  int[] mColors;

private  static  int[] createColors() {
     int[] colors =  new  int[STRIDE * HEIGHT];
     for ( int y =  0; y < HEIGHT; y++) {
         for ( int x =  0; x < WIDTH; x++) {
             int r = x *  255 / (WIDTH -  1);
             int g = y *  255 / (HEIGHT -  1);
             int b =  255 - Math.min(r, g);
             int a = Math.max(r, g);
            colors[y * STRIDE + x] = (a <<  24) | (r <<  16) | (g <<  8) | b;
        }
    }
     return colors;
}

public MyCreateBitmapView(Context context) {
     super(context);

    mColors = createColors();
     int[] colors = mColors;

    mBitmaps =  new Bitmap[ 4];
     // these three are initialized with colors[]
    mBitmaps[ 0] = Bitmap.createBitmap(colors,  0, STRIDE, WIDTH, HEIGHT,
                                      Bitmap.Config.ARGB_8888);
    mBitmaps[ 1] = Bitmap.createBitmap(colors,  0, STRIDE, WIDTH, HEIGHT,
                                      Bitmap.Config.RGB_565);
    mBitmaps[ 2] = Bitmap.createBitmap(colors,  0, STRIDE, WIDTH, HEIGHT,
                                      Bitmap.Config.ARGB_4444);

    mBitmaps[ 3] = Bitmap.createBitmap(WIDTH, HEIGHT,
                                      Bitmap.Config.ARGB_8888);
    mBitmaps[ 3].setPixels(colors,  0, STRIDE,  00, WIDTH, HEIGHT);
}

@Override
protected  void onDraw(Canvas canvas) {
     super.onDraw(canvas);
     for ( int i =  0; i < mBitmaps.length; i++) {
        canvas.drawBitmap(mBitmaps[i],  00, null);
        canvas.translate(mBitmaps[i].getHeight() +  5,   0);
    }
}




createBitmap的Matrix使用方法,背景缩放和透明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int width =  600;
int height =  1024;

int widthDrawable = backGroundMap.getWidth();
int heightDrawable = backGroundMap.getHeight(); //获取背景图片的宽和高

float scaleWidth = ( float)width / widthDrawable;
float scaleHeight = ( float)height / heightDrawable;  //宽高比

Bitmap resizeBmp;
Matrix matrix =  new Matrix();

if(scaleWidth < scaleHeight) {
     float scale = scaleHeight; //取大的
    matrix.postScale(scale, scale); //缩放比例
     int xStart = ( int)(widthDrawable - widthDrawable / scale) /  2;

     /*
     * Bitmap source:要从中截图的原始位图
     * int x:起始x坐标
     * int y:起始y坐标
     * int width:要截的图的宽度
     * int height:要截的图的宽度
     * x+width must be <= bitmap.width()不然会报错
     * 原理是先截图再缩放,而不是先缩放再截图!!
     */

    resizeBmp = Bitmap.createBitmap(backGroundMap, xStart,  0, ( int)(widthDrawable / scale),
                                    heightDrawable, matrix, true);
else {
     float scale = scaleWidth;
    matrix.postScale(scale, scale);
     int yStart = ( int)(scaleHeight - scaleHeight / scale) /  2;
    resizeBmp = Bitmap.createBitmap(backGroundMap,  0, yStart, widthDrawable,
                                    ( int)(heightDrawable / scale), matrix, true);
}

//Bitmap 转化为 Drawable
BitmapDrawable drawable =  new BitmapDrawable(getResources(), resizeBmp);
setBackgroundDrawable(drawable);
//getBackground().setAlpha(150);    //设置背景透明度
       Android Bitmap Api总结和使用方法_第1张图片       Android Bitmap Api总结和使用方法_第2张图片

Bitmap的优化:
Android分给应用的虚拟机堆栈只有8M,而加载图片时会很消耗资源,只要图片只够大,也就很容易把8M的内存消耗光,就 会出现OOM(Out Of Memory)的问题。所以,应用程序要很注意对内存的优化:
优化的方法如下:
1)主动回收Bitmap的内存
在Android中,很多关于UI的实现都是在Jni用C语言实现的。这样做主要是因为,对图片的处理要做大量的位操作,在C语言中,位操作更快,更容易。C语言的效率会更高,对于大量数据的处理可以更快。但是这就会出现一个问题,在Jni里面开辟的内存,数组,缓存等虚拟机是无法自动回收的。只能是Jni程序员在某个时间手动回收。也有可能是程序退出的时候才回收,但我们在程序使用的过程中会产生很多无用的Bitmap,这时,这些Bitmap就要我们在上层手动回收了:
在Android 的 Bitmap里就提供了主动回收的函数 recycle():
我们可能是返回,退出的时候回收,也可能在应用隐藏到后台的时候回收,也可以 在线程退出的时候回收,可以对Bitmap的临时变量做回收。可以在Bitmap转换后把原来的进行回收。 需要回收的地方可能很多,这里只是稍微提供一下思路
1
2
3
4
if(!bmp.isRecycle() ) {
    bmp.recycle()    //回收图片所占的内存
    system.gc()   //提醒系统及时回收
}


2)捕获异常
这里主要是要捕获分配Bitmap时会出现OutOfMemory异常,保证出现问题后,程序可以断续运行:
1
2
3
4
5
6
7
8
9
10
11
Bitmap bitmap = null;
try {
     // 实例化Bitmap
    bitmap = BitmapFactory.decodeFile(path);
catch (OutOfMemoryError e) {
     //
}
if (bitmap == null) {
     // 如果实例化失败 返回默认的Bitmap对象
     return defaultBitmapMap;
}
但是要注意: OutOfMemoryError是一个Error,如果是直接捕获Exception是无捕获的

3)压缩图片大小和内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

//获得原始图片的大小 
BitmapFactory.Options options =  new BitmapFactory.Options();
//inJustDecodeBounds=true时只加载图片的宽高:options.outWidth 和 options.outHeight
options.inJustDecodeBounds = true;  
Bitmap bmp = BitmapFactory.decodeFile(path, options); /* 这里返回的bmp是null */

//缩小图片
int height = options.outHeight *  200 / options.outWidth;
//压缩图片容量,如果没有这句,只是缩小图片到指定尺寸,不会会影响内存
options.inSampleSize = options.outWidth /  200/*图片长宽方向缩小倍数*/
options.outWidth = 200;
options.outHeight = height; 
options.inJustDecodeBounds = false;

Bitmap bmp = BitmapFactory.decodeFile(path, options);
image.setImageBitmap(bmp);

4)通过临时缓存保存Bitmap
对于大用到Bitmap,和快速重复更新的情况下就要通过临时变量对保存Bitmap,避免重复加载和创建,例如ListView的里会不断刷新Bitmap,这里就要用在ListVeiw里用一个临时变量保存ListView的Bitmap,数据等。具体看一下ListView的优化



参考文章:
http://blog.sina.com.cn/s/blog_5da93c8f0102v2x4.html
http://www.cnblogs.com/igrl/archive/2010/07/30/Bitmap_createBitmap.html
http://www.jb51.net/article/36631.htm

你可能感兴趣的:(Android应用编程,UI)