您的位置:首页 > 移动开发 > Android开发

Android Bitmap Api总结和使用方法

2015-11-11 14:29 627 查看
在学习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, 0, 0, WIDTH, HEIGHT);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

for (int i = 0; i < mBitmaps.length; i++) {

canvas.drawBitmap(mBitmaps[i], 0, 0, 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); //设置背景透明度




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

/article/7005361.html

http://www.jb51.net/article/36631.htm
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: