位图基本概念
位图文件的定义:扩展名可以是.bmp或者.dib,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2、4、8、16、24和32位色彩。
根据定义,知道了一个位图的分辨率和色彩,就可以计算出该位图的所占空间大小。如一幅1024×768分辨率的32位真彩图片,其所占存储字节数为:1024×768×32/(8*1024)=3072KB
位图文件的特点:图像效果好,但是非压缩格式的,需要占用较大存储空间,不利于在网络上传送。jpg格式则恰好弥补了位图文件这个缺点。
Bitmap 对象的创建方法
Bitmap类首先提供了一个静态方法createBitmap来创建Bitmap对象.该方法有几个重载的方法,如下图所示:
Bitmap.createBitmap(Bitmap src);方法功能:复制一个和源位图一样的新位图。方法参数为一个源Bitmap对象。查看源码注释,用此方法创建的位图是不可改变的。不可改变是什么意思?下面我将详细描述一下。bitmap对象有一个布尔类型的属性叫做Mutable,意思是可改变的。其值有true和false两个。描述的是外界能否修改该图片的像像素点。通过方法 bitmap.isMutable();可以判断一个bitmap对象是否是可以改变的。当一个bitmap对象是不可改变的时候,那么bitmap.setPixel();方法将不可掉用,掉用后会导致异常,该方法就是设置bitmap的像素的。有些地方就需要传入一个必须是可以改变的bitmap对象的,比如Canvas c=new Canvas(bitmap);这里的bitmap就必须是可以改变的,否则报异常,源码注释为(bitmap Specifies a mutable bitmap for the canvas to draw into)。用此方法创建的bitmap对象还有一个特点,即创建的新图片和源图片的像素密度是相同的。最后创建的新图片和源图片大小是一样的,甚至(有时候)两个图片的地址即指向的对象是一样的,两个变量指向同一个对象。为什么用有时候,看源码注释(The new bitmap may be the same object as source, or a copy may have been made),源码说有时候是该源图片本身,有得时候是源图片的副本。如果源图片为不可改变的,那么新的图片即和源图片为一个对象,如果源图片是可以改变的,那么新图片为源图片的副本,即是两个不同的对象。试想,如果源图片是可以改变的,新的图片也和源图片指向同一个对象,那么新的图片被编辑了源图片也会随之改变。而这样是不对的!
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height);方法功能:在源位图上裁剪出一个新位图。方法参数为一个源Bitmap对
象,源图片中x方向的起始像素,源图片中y方向的起始像素,截图宽度(单位为像素),截图高度(单位为像素);查看源码注释,用此方法创建的位图是不可以
被改变的。新图片和源图片像素密度相同,新图片可能是源图片的副本,也可能是源图片的全部或者部分副本。具体解释见上边。
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter);方法功能:在源位图上裁剪出一个新位
图,并可以定义矩阵变换新位图。方法参数为一个源Bitmap对象,源图片中x方向的起始像素,源图片中y方向的起始像素,截图宽度(单位为像素),截图高度
(单位为像素),用于新图片变换的矩阵matrix,当矩阵的变换不只有平移时,如果此参数设置为真,进行滤波处理来改善图片的质量。查看源码注释,用此方法
创建的位图是不可以被改变的。新图片和源图片像素密度相同,新图片可能是源图片的副本,也可能是源图片的全部或者部分副本。具体解释见上边。
Bitmap createBitmap(int width, int height, Config config);方法功能:创建一个可以被改变的新位图,不需要源位图。方法参数为新图片的宽度,新
图片的高度,图片的质量。查看源码注释,用此方法创建的位图对象是可以被改变的。新位图的像素密度为和手机硬件相关的值,因为新位图的像素密度默认的是
调用bitmap.getDensity();方法得到的,bitmap.getDensity()方法最终就是获得手机像素密度。
Bitmap createBitmap(DisplayMetrics display, int width,int height, Config config);方法功能:创建一个可以被改变的新位图,位图像素密度为自定义值,不需要源位
图。方法参数为DisplayMetrics对象,新图片的宽度,新图片的高度,图片的质量。查看源码注释,用此方法创建的位图对象是可以被改变的。新位图像素密度为
自定义值。可以通过例如display.densityDpi=480;指定像素密度。(像素密度为屏幕上一英寸包含的像素点的个数,一英寸位2.54cm)
Bitmap createBitmap(int[] colors,int width, int height, Config config);方法功能:创建一个不可以被改变的新位图,需要每个像素点对应的颜色
值,即颜色数组。方法参数为像素颜色值的数组,新图片的宽度,新图片的高度,图片的质量。查看源码注释,用此方法创建的位图对象是不可以被改变的。新位
图的像素密度为和手机硬件相关的值,因为新位图的像素密度默认的是调用bitmap.getDensity();方法得到的,bitmap.getDensity()方法最终就是获得手机像素
密度。新图片的生成是根据颜色数组的值,依次从左到右从上到下逐行生成的。
--------------------------------------------------------------------------------------------------------------
如果是复制一个图片,可以调用bitmap.copy(Config config, boolean isMutable);方法,方法功能:创建一个bitmap的副本。方法参数为新图片的质量,新图片是否是可
以改变的。新图片和源图片拥有相同的像素密度。
Bitmap 对象的获取方法
首先介绍一个类,BitmapFactory类。源码文档注释为:可以从多种渠道创建一个位图对象,包括文件,流和字节数组(其实还包括资源)。BitmapFactory类通过各种解码的方法从多种渠道获得位图对象,其中,BitmapFactory类中还有一个静态内部类叫做Options类,Options就是控制解码时一些具体设置的。BitmapFactory类的解码方法如下图所示:
BitmapFactory.decodeResource(Resources res, int id);方法功能:从资源文件中解析出一个位图对象,返回的位图是不可改变的。方法参数分别为资源 的对象,资源中位图文件的id。
BitmapFactory.decodeResource(Resources res, int id, Options opts);方法功能:从资源文件中解析出一个位图对象,解析时用Options对象设置解码规则,返回的位图如不特别设置默认为不可改变的。方法参数分别为资源 的对象,资源中位图文件的id,Options对象。Options对象的创建方式为BitmapFactory.Options options=new BitmapFactory.Options();在这里介绍一下Options类中一些字段的含义:
boolean inMutable:解码出的位图对象是否是可以改变的,默认是不可以改变的。
boolean inJustDecodeBounds:如果设置为真,解码器会返回空,并不会有bitmap对象返回。但是以out...开头的属性会被赋值。这就可以允许调用者在不把图片加载到内存的情况下来查询图片的一些信息。通常和outWidth和outHeight字段一起使用,还有outMimeType(文件类型),这些属性会被赋值。如果inJustDecodeBounds的值为真,outWidth和outHeight的值为源图片的宽度上像素和高度上像素。如果为假,outWidth和outHeight的值为缩放后的像素值。如果解码失败值为-1.
int inSampleSize:采样比率,如果其值大于1那么解码器进行第二次采样并加载一个缩放后的图片进入内存,其值如果小于1,会被当作等于1处理。比如,其值等于2,那么宽度和高度像素都变成以前的1/2,像素个数就变成以前的1/4.源码说inSampleSize的值要为2的幂指数,否则会被下调到最近的那个2的幂指数。可是经我在6.0.1下测试,并没有下调,这个还没搞清楚。这个字段在显示缩略图的时候可以用到,并配合用inJustDecodeBounds得到图片的尺寸。
boolean inPremultiplied:在无参构造方法中赋值为true,即默认为真。如果为真,位图的色彩通道会被透明通道预先并联起来。如果设置为false,在将图片绘制到canvas或者view system上会报错。一般情况下此值都是为true的。
boolean inDither:设置图像抖动。在无参构造方法中赋值为false,默认为false。抖动解码会增强图像的质量,使图像的颜色过渡更加自然。
boolean inPreferQualityOverSpeed:进行质量优化,但会牺牲速度。通常指针对jpg格式图片有效果。
int inDensity:设置图片本身的像素密度。如果inScaled属性设置为true(默认为真,在构造方法中初始化了),inDensity属性和inTargetDensity属性的值不一样的话,bitmap对象会在返回前缩放以满足inTargetDensity。如果inDensity的值为0,在解码资源中图片和资源流时,会根据bitmap的resource设置像素密度,其他解码方式则不则不会设置像素密度。
int inTargetDensity:bitmap被画出来的时候的目标像素密度。和inDensity以及inScaled一起使用,用来决定在bitmap返回之前是否以及怎么缩放bitmap。如果此值为0,那么在解码资源和资源流时会结合资源对象的DisplayMetrics设置像素密度。其他解码方式会不进行缩放,像素密度保留原样。
boolean inScaled:如果此属性为true(默认),inDensity和inTargetDensity的值不为0,bitmap在加载的时候会被缩放以满足像素密度inTargetDensity。
int inScreenDensity:屏幕实际应用的像素密度。
boolean inInputShareable:API21以上,此属性将失效。
boolean inPurgeable:API21以上,此属性将失效。
BitmapFactory.decodeFile(String pathName);方法功能:从文件中解析出一个位图对象,返回的位图是不可改变的。方法参数为位图文件的路径。返回的位图默认为不可改变的。
BitmapFactory.decodeFile(String pathName, Options opts);方法功能:从文件中解析出一个位图对象,方法参数为位图文件的路径,Options对象。解析时用Options对象设置解码规则,返回的位图如不特别设置默认为不可改变的。
BitmapFactory.decodeByteArray(byte[] data, int offset, int length);方法功能:从字节数组中解析出一个bitmap对象。方法参数:含有图片数据的字节数组,解码时在数组中的偏移量,要解码的数组元素个数(长度)。默认返回一个不可改变的bitmap对象。
BitmapFactory.decodeByteArray(byte[] data, int offset, int length,Options opts);方法功能:从字节数组中解析出一个bitmap对象。方法参数:含有图片数据的字节数组,解码时在数组中的偏移量,要解码的数组元素个数(长度)Options 对象。解析时用Options对象设置解码规则,如果不特别设置默认返回一个不可改变的bitmap对象。
BitmapFactory.decodeFileDescriptor(FileDescriptor fd);方法功能:从文件描述符中解码出一个bitmap对象。由于文件描述符内的位置在图片返回的时候不会改变,所以可以再次使用。方法参数:FileDescriptor 对象。返回的图片默认是不可以被改变的。
BitmapFactory.decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts);方法功能:从文件描述符中解码出一个bitmap对象。由于文件描述符内的位置在图片返回的时候不会改变,所以可以再次使用。方法参数:FileDescriptor 对象,Rect 对象,Options 对象。返回的图片如果不特别设置默认是不可以被改变的。如果Rect 对象不为空,那么如果存在的话为bitmap返回填充矩形,否则填充设置为[-1,-1,-1,-1],如果没有bitmap返回填充不会改变。
BitmapFactory.decodeStream(InputStream is);方法功能:从一个包含bitmap数据的输入流中解析出一个bitmap。方法参数:包含bitmap数据的输入流。返回一个不可以被改变的bitmap。
BitmapFactory.decodeStream(InputStream is, Rect outPadding, Options opts);方法功能:从一个包含bitmap数据的输入流中解析出一个bitmap。方法参数:包含bitmap数据的输入流,Rect 对象,Options 对象。返回的bitmap对象如果不特别设置默认为不可改变的。如果Rect 对象不为空,那么如果存在的话为bitmap返回填充矩形,否则填充设置为[-1,-1,-1,-1],如果没有bitmap返回填充不会改变。
BitmapFactory.decodeResourceStream(Resources res, TypedValue value,InputStream is, Rect pad, Options opts);方法功能:从一个来自资源的输入流中解码得到一个bitmap对象。
未完待续