Android Bitmap Api总结和使用方法

本文详细介绍了Bitmap的创建方法,包括使用BitmapFactory和Bitmap.createBitmap的各种API,并提供了具体的使用案例。同时,还探讨了Bitmap的优化策略,如主动回收内存、异常处理、图片压缩等。
在学习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);    //设置背景透明度
             

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的优化



参考文章:
android Bitmap用法总结 Bitmap用法总结 1、Drawable → Bitmap public static Bitmap drawableToBitmap(Drawable drawable) { Bitmap bitmap = Bitmap .createBitmap( drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bitmap); // canvas.setBitmap(bitmap); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); drawable.draw(canvas); return bitmap; } 2、从资源中获取Bitmap Resources res=getResources(); Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.pic); 3、Bitmap → byte[] private byte[] Bitmap2Bytes(Bitmap bm){ ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG, 100, baos); return baos.toByteArray(); } 4、byte[] → Bitmap private Bitmap Bytes2Bimap(byte[] b){ if(b.length!=0){ return BitmapFactory.decodeByteArray(b, 0, b.length); } else { return null; } } 5、保存bitmap static boolean saveBitmap2file(Bitmap bmp,String filename){ CompressFormat format= Bitmap.CompressFormat.JPEG; int quality = 100; OutputStream stream = null; try { stream = new FileOutputStream("/sdcard/" + filename); } catch (FileNotFoundException e) { // TODO Auto-generated catch block Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. e.printStackTrace(); } return bmp.compress(format, quality, stream); } 6、将图片按自己的要求缩放 // 图片源 Bitmap bm = BitmapFactory.decodeStream(getResources() .openRawResource(R.drawable.dog)); // 获得图片的宽高 int width = bm.getWidth(); int height = bm.getHeight(); // 设置想要的大小 int newWidth = 320; int newHeight = 480; // 计算缩放比例 float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // 取得想要缩放的matrix参数 Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); // 得到新的图片 Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true); // 放在画布上 canvas.drawBitmap(newbm, 0, 0, paint); 相关知识链接:http://www.eoeandroid.com/thread-3162-1-1.html 7、bitmap的用法小结 BitmapFactory.Options option = new BitmapFactory.Options(); option.inSampleSize = 2; //将图片设为原来宽高的1/2,防止内存溢出 Bitmap bm = BitmapFactory.decodeFile("",option);//文件流 URL url = new URL(""); InputStream is = url.openStream(); Bitmap bm = BitmapFactory.decodeStream(is); android:scaleType: android:scaleType是控制图片如何resized/moved来匹对ImageView的size。ImageView.ScaleType / android:scaleType值的意义区别: CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分 显示 CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长 (宽) CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片 长/宽等于或小于View的长/宽 Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示 FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置 FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置 FIT_XY / fitXY 把图片 不按比例 扩大/缩小到View的大小显示 MATRIX / matrix 用矩阵来绘制,动态缩小放大图片来显示。 //放大缩小图片 public static Bitmap zoomBitmap(Bitmap bitmap,int w,int h){ int width = bitmap.getWidth(); int height = bitmap.getHeight(); Matrix matrix = new Matrix(); float scaleWidht = ((float)w / width); float scaleHeight = ((float)h / height); matrix.postScale(scaleWidht, scaleHeight); Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true); return newbmp; } //将Drawable转化为Bitmap public static Bitmap drawableToBitmap(Drawable drawable){ int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0,0,width,height); drawable.draw(canvas); return bitmap; Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. } //获得圆角图片的方法 public static Bitmap getRoundedCornerBitmap(Bitmap bitmap,float roundPx){ Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap .getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } //获得带倒影的图片方法 public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap){ final int reflectionGap = 4; int width = bitmap.getWidth(); int height = bitmap.getHeight(); Matrix matrix = new Matrix(); matrix.preScale(1, -1); Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height/2, width, height/2, matrix, false); Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height/2), Config.ARGB_8888); Canvas canvas = new Canvas(bitmapWithReflection); canvas.drawBitmap(bitmap, 0, 0, null); Paint deafalutPaint = new Paint(); Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. canvas.drawRect(0, height,width,height + reflectionGap, deafalutPaint); canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null); Paint paint = new Paint(); LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP); paint.setShader(shader); // Set the Transfer mode to be porter duff and destination in paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // Draw a rectangle using the paint with our linear gradient canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint); return bitmapWithReflection; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值