Android Bitmap 图片

AndroidBitmap图片的显示,是一个比较头疼的问题,Bitmap图片占用内存大,稍不注意就会千万OOM,为什么它会如此占内存呢?

Bitmap.Config

图片的Config,它定义了pixel像素的存储规则,它将直接影响图片的质量。

This affects the quality (color depth) and the ability to display transparent/translucent colors.

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public enum Config {
// these native values must match up with the enum in SkBitmap.h
/** 每个像素被存储在一个表示透明度的单通道里面,它不存储颜色值。
* Each pixel is stored as a single translucency (alpha) channel.
* This is very useful to efficiently store masks for instance.
* No color information is stored.
* With this configuration, each pixel requires 1 byte of memory.
*/
ALPHA_8 (1), // 每个像素点占用1byte的内存
/** 每个像素存储在2个byte中,仅存储了RGB通道的颜色值,红绿蓝分别占用5/6/5
* bit的空间,对应的存储值最大分别是32, 64, 32
* Each pixel is stored on 2 bytes and only the RGB channels are
* encoded: red is stored with 5 bits of precision (32 possible
* values), green is 6(64 possible values) and blue is 5.
*
* This configuration can produce slight visual artifacts depending
* on the configuration of the source.
* 这个配置通常用于对颜色要求不高的非透明的图片.
* This configuration may be useful when using opaque bitmaps
* that do not require high color fidelity.
*/
RGB_565 (3),
/** 每个像素存在2个byte中,包含RGB颜色值和alpha透明度值。透明度存在4bit中(最大值16)
* Each pixel is stored on 2 bytes. The three RGB color channels
* and the alpha channel (translucency) are stored with a 4 bits
* precision (16 possible values.)
* 当应用需要存储透明度值,同时又需要节约内存的时候,使用该配置。
* 建议使用ARGB_8888代替该配置
* Note: KITKAT版本之后,使用该配置时,系统将自动使用ARGB_8888配置替换。
*/
@Deprecated
ARGB_4444 (4),
/** 每个像素存储占用4个byte,每个通道(RGB和Alpha)都使用在8bit(最大值256)进行存储。
* Each pixel is stored on 4 bytes. Each channel (RGB and alpha
* for translucency) is stored with 8 bits of precision (256
* possible values.)
* 推荐使用该配置。
* This configuration is very flexible and offers the best
* quality. It should be used whenever possible.
*/
ARGB_8888 (5),
/** 每个像素存储占用8个byte。每个通道值存储成float值。
* Each pixels is stored on 8 bytes. Each channel (RGB and alpha
* for translucency) is stored as a
* {@link android.util.Half half-precision floating point value}.
* 适合用于存储高密度的图片
* This configuration is particularly suited for wide-gamut and
* HDR content.
*/
RGBA_F16 (6),
/** 一种特殊的配置,图片只被存储在graphic内存区域,并且图片的像素值不能被修改
* Special configuration, when bitmap is stored only in graphic memory.
* Bitmaps in this configuration are always immutable.
* 当一个图片只需要用于显示在screen上,这是最佳的配置。
*/
HARDWARE (7);
private static Config sConfigs[] = {
null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
};
}

生成图片

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
public void generateBitmap(@SuppressWarnings("unused") View unused) {
ByteBuffer buffer = ByteBuffer.allocate(256 * 256 * 4);
byte[] buffers = buffer.array();
// 创建4个随机的RGBA颜色值
byte[][] colors = new byte[4][4];
for (int i = 0; i < 4; i++) {
colors[i][0] = (byte) (256 * Math.random() - 128);
colors[i][1] = (byte) (256 * Math.random() - 128);
colors[i][2] = (byte) (256 * Math.random() - 128);
colors[i][3] = (byte) 255; //(byte) (256 * Math.random() - 128);
}
// 写入颜色值
for (int y = 0; y < 256; y++) {
for (int x = 0; x < 256; x++) {
int baseIndex = (y * 256 + x) * 4;
buffers[baseIndex] = colors[x % 4][0];
buffers[baseIndex + 1] = colors[x % 4][1];
buffers[baseIndex + 2] = colors[x % 4][2];
buffers[baseIndex + 3] = colors[x % 4][3];
}
}
Bitmap bmp = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(buffer); // 将颜色值copy到bitmap
mImageView.setImageBitmap(bmp);
}

其它方法

  • copyPixelsToBuffer: 将Pixel值拷贝到Buffer中
  • copyPixelsFromBuffer: 从Buffer中拷贝Pixel值