Bitmap(位图) 是android系统图像处理中很重要的类。它将图像描述为像素点矩阵,每个像素点占有一定内存。一个像素点可以有A(透明度)R(红色)G(绿)B(蓝)四个通道,由这几个通道的值来一起描述这个像素点的色值。
在绘制图像,操作图像,如放大,旋转等,都会用到Bitmap。
这里主要讲解Bitmap的一些重要属性和方法。
重要属性:
Width,Height
宽高。宽高有多少个像素。
Config
Bitmap在内存中存储的方式。
public final Config getConfig()
Bitmap.Config
这是Bitmap的一个内部enum。
public static finalBitmap.Config ALPHA_8
一个像素点1字节,只存储Alpha通道,即透明度。
public static finalBitmap.Config ARGB_4444
一个像素点2个字节。ARGB各占4位。
API13已被废弃。建议用ARGB_8888
public static finalBitmap.Config ARGB_8888
一个像素点4个字节。ARGB各占1字节。
public static finalBitmap.Config RGB_565
一个像素点2个字节。
R占5位,G占6位,B占5位。不透明,没有Alpha通道。
density
密度。默认是当前屏幕的密度。也可以设置。
public void setDensity(int density) public int getDensity()
当Bitmap往Canvas上画时,会根据Canvas的density进行缩小,放大。
Bitmap中有一个方法:
static public int scaleFromDensity(int size, int sdensity, int tdensity) { if (sdensity == DENSITY_NONE ||tdensity == DENSITY_NONE || sdensity == tdensity) { return size; } // Scale by tdensity / sdensity,rounding up. return ((size * tdensity) + (sdensity>> 1)) / sdensity; }
就是根据当前的密度,目标的密度,算出新的尺寸,(四舍五入)。
mutable
像素点是否可以修改。
public final boolean isMutable()
为true的话,可以通过下面的方法,
public void setPixel(int x, int y, int color)
将(x,y)坐标点颜色设为 color
创建Bitmap:
public static Bitmap createBitmap(…)
Bitmap中有一系列createBitmap的(重载)方法。
可以根据给定色值矩阵来创建一个bitmap。
可以根据一个Bitmap(源Bitmap),来创建一个Bitmap。这里有一个问题,返回的Bitmap有可能与源Bitmap是一个对象,而不是重新创建。这样的话,其中一个调用了recycle()释放的话,另一个当然也不能用了。
可以创建相对源Bitmap变化了的Bitmap,如位移,旋转,放大缩小等。利用
Matrix。
public Bitmap copy(Config config, boolean isMutable)
根据现有Bitmap,参数,复制一个新的Bitmap
一些参数:
DisplayMetrics display
只是用了display中的density,设置为Bitmap的density
Bitmap.Config config
像素存储格式
Matrix m
这是一个矩阵。利用它可以创建放大缩小,旋转等的图片。
Bitmap的图像内容是一个矩阵,对矩阵进行放大缩小,位移,旋转等可以通过与另一个矩阵相乘来实现,这是线性代数的内容。
boolean filter
对图片缩小时没有影响。对图片放大时,true会得到平滑的图片。false得到的图片会一块块的像素点。
参考:http://stackoverflow.com/questions/2895065/what-does-the-filter-parameter-to-createscaledbitmap-do
BitmapFacotory中也有一系列创建Bitmap的静态方法:
BitmapFactory.decode...(...)
可以:
从文件decode出Bitmap
从Inputstream中decode出Bitmap
持久化
Bitmap实现了Parcelable接口。可以通过Parcelable传输,持久化。
可以写入输出流中:
public boolean compress(CompressFormat format,int quality, OutputStream stream)
CompressFormat |
图片格式 JPEG , PNG WEBP |
quality |
压缩率。0压缩最大,100不压缩。PNG会忽略此值 |
可以写入到Buffer 中:
public void copyPixelsToBuffer(Buffer dst) publicvoid copyPixelsFromBuffer(Buffer src)
一些方法:
public int getGenerationId ()
当Bitmap被修改时,generationId会变,可以通过这个值来判断图片有没有被修改。
public final boolean isPremultiplied()
Multipy是乘的意思,乘法的乘。字面上的意思是有没有被“预乘”过,这是什么意思呢?
看个例子:
如果一个颜色是(128,255, 0, 0)即50%透明度的红色,“预乘”后,就成了(128,
128, 0, 0)。
对了,就是把初始色值的RGB值与透明度相乘。
这有什么用呢?
一个有透明度的Bitmap要被系统画出来,就必须先被“预乘”,否则会抛出异常。所以有个“预”(pre)字。
对没有透明度的Bitmap来说,这个没有意义。
public void recycle ()
清除本地对象,清除只想像素数据(pixel data)的引用。
确定不用了才能掉。否则会出问题。
一般不需要调用。一般情况GC的回收机制能解决问题。
public final boolean isRecycled ()
有没有被回收。如果没回收了的话,就不能访问它的像素,不能被画出。
public void setConfig (Bitmap.Configconfig)
public void reconfigure (int width, int height,Bitmap.Configconfig)
修改Bitmap的宽,高,config,但是并没有修改Bitmap的像素数据。这样避免了重新分配像素点矩阵的内存,减少了内存分配开销,也有更好的性能。
只支持由大(占用内存)变小。由小变大会抛异常。
占用内存
Bitmap中,占用内存的主要是 像素点矩阵占用的内存,其他的基本可以忽略。
像素点矩阵占用的内存大小=像素点数 * 每个像素点占用内存 = 长*宽*每个像素点占用内存。
Bitmap格式是非常占用内存的,加载大图片时经常会出现oom(内存溢出)。
按照 长*宽*每个像素点占用内存 算下的可能比实际占用的要小。
使用 reconfigure() 将bitmap由大变小。之前说过,调用这个方法时,bitmap尺寸小了,但是像素点矩阵并没有变。
获取占用内存: