Android小白研究下Bitmap

在Android开发中我们会在很多时候用到图片,这个时候我们就需要用到Bitmap了,在Android开发中我们使用的图都要转换成位图。但是我们并不能通过Bitmap的构造方法来实例化一个Bitmap,官方提供了BitmapFactory来的静态方法来实例化Bitmap
当我们使用Bitmap的时候很容易的就会导致应用程序的内存被消耗完,所以使用Bitmap的时候一定要做好优化。

Config

在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
public enum Config {
/**
*每一个像素存一个alpha通道的值,不存储颜色信息,适合做遮罩层。每个像素占1byte。
*/
ALPHA_8 (1),
/**
*每个像素占2byte,只有RBG通道色值,Red占5bit,Green占6bit,Blue占5bit。
*/
RGB_565 (3),
/**
*因为质量太低,推荐使用ARGB_8888代替
*/
@Deprecated
ARGB_4444 (4),
/**
* 官方推荐使用
*每一个像素占4byte,每一个通道(ARGB)占8bit(256个值).
*灵活切画面质量好
*/
ARGB_8888 (5);
}

他的主要作用就是让我们来设置画面的质量的,

创建一个Bitmap

查看bitmap的源码我们会看到一些createBitmap()方法,但是我们创建Bitmap使用的最多的是BitmapFactory类的方法。

1
Bitmap bitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.ARGB_8888);

通过上面的方法可以创建一个空白的Bitmap。

BitmapFactory

Options类

Options类用来设置解码的参数。其中主要有:

  • public Bitmap inBitmap;

  • public boolean inJustDecodeBounds; 如果设置为true,解析器将返回null,但是out...字段会设置上值。

  • public int inSampleSize; 如果设置的值>1那么解析器将会对原始图片进行抽取,返回一个更小的图片。解析器会使用2的次方,其他的值会向下转为最近的2的幂。
  • public boolean inDither;
  • public int inDensity; bitmpa使用的像素密度。
  • public int inTargetDensity;
  • public int inScreenDensity;
  • public boolean inScaled;
  • public int outWidth; 图片的宽度
  • public int outHeight; 图片的高度
  • public String outMimeType; 如果知道图片的MIME类型就设置上,如果不知道就设置为null

当我们想对图片进行压缩的时候,我们就要使用到Options。先看下代码:

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
BitmapFactory.Options options = new BitmapFactory.Options();
//设置为true,先让解析器解析出图片的大小信息。
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher,options);
//之后他们通过这个得到了图片大小信息的options来计算压缩的比例。
options.inSampleSize = calculateInSampleSize(options,200,200);
options.inJustDecodeBounds = false; //之后设置为false,为了获取到bitmap。
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher, options);//之后就可以通过这个options来获取自己期望的bitmap了。
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}

这里的calculateInSampleSize方法是官方文档中提供的用来计算InSampleSize值的方法。

decode方法

使用decode系列方法来得到bitmap对象
图片描述

Recycle

Bitmap不再使用的时候记得将其回收,以免内存泄漏

1
2
3
if (!bitmap.isRecycled()) {
bitmap.recycle();
}

复制Bitmap

Bitmap有一个coty()方法用来复制一个Bitmap.源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Tries to make a new bitmap based on the dimensions of this bitmap,
* setting the new bitmap's config to the one specified, and then copying
* this bitmap's pixels into the new bitmap. If the conversion is not
* supported, or the allocator fails, then this returns NULL. The returned
* bitmap initially has the same density as the original.
*
* @param config The desired config for the resulting bitmap
* @param isMutable True if the resulting bitmap should be mutable (i.e.
* its pixels can be modified)
* @return the new bitmap, or null if the copy could not be made.
*/
public Bitmap copy(Config config, boolean isMutable) {
checkRecycled("Can't copy a recycled bitmap");
Bitmap b = nativeCopy(mNativePtr, config.nativeInt, isMutable);
if (b != null) {
b.setPremultiplied(mRequestPremultiplied);
b.mDensity = mDensity;
}
return b;
}

有时我们创建的Bitmap是无法更改的。但是有时候我们可能需要对Bitmap进行更改,这个时候我们就可以使用copy(Config,true)