首页 > 代码库 > Bitmap解析

Bitmap解析

Bitmap(位图) android系统图像处理中很重要的类。它将图像描述为像素点矩阵,每个像素点占有一定内存。一个像素点可以有A(透明度)R(红色)G(绿)B(蓝)四个通道,由这几个通道的值来一起描述这个像素点的色值。


在绘制图像,操作图像,如放大,旋转等,都会用到Bitmap。

这里主要讲解Bitmap的一些重要属性和方法。


重要属性:

WidthHeight

宽高。宽高有多少个像素。

 

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个字节。 R5位,G6位,B5位。不透明,没有Alpha通道。 

density

密度。默认是当前屏幕的密度。也可以设置。


public void setDensity(int density)
public int getDensity()

BitmapCanvas上画时,会根据Canvasdensity进行缩小,放大。

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,设置为Bitmapdensity

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...(...)

可以:

从文件decodeBitmap

InputstreamdecodeBitmap


持久化

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尺寸小了,但是像素点矩阵并没有变。
获取占用内存:
<script src="https://code.csdn.net/snippets/559822.js" type="text/javascript"></script>












Bitmap解析