Bitmap
Drawable,Canvas和Bitmap
- drawable:通用的图形对象,用于装载常用格式的图像,既可以是PNG,JPG,gif这样的图像。同时包含13种Drawable类型的可视化对象,StateListDrawable,BitmapDrawable...
- Canvas:画布,也就是我们可以绘制的区域。提供了drawXXX()等方法来便捷的绘制图形。
- Bitmap:是一种存储像素的数据结构,通过这个对象可以得到一系列的图像属性。还可以对图像进行旋转,切割,放大,缩小等操作。
个人理解:Bitmap是一种数据结构,存储像素信息。Drawable 储存的是 对 Canvas 的一系列操作。而 BitmapDrawable 储存的是「把 Bitmap 渲染到 Canvas 上」这个操作。
Bitmap,BitmapFactory,BitmapFacotry.Options
获取Bitmap
由于Bitmap的构造方法私有化,所以我们不能在外部直接实例化一个Bitmap对象。我们只能通过BitmapFactory来得到Bitmap对象。
BitmapFractory常用获取Bitmap的方法:
途径 | 方法 |
---|---|
从文件中解析 | decodeFile(String pathName, Options), decodeFile(String pathName) |
从res/目录下解析 | decodeResource(Resources res,int id), decodeResurce(Resources res, int id, Options) |
从字节数组中解析 | decodeByteArray(byte[] data, int offset, int length), decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts) |
从流中解析 | decodeStream(InputStream is), decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts) |
通过上述表格我们发现,无论是哪一种途径得到的Bitmap都有一种重载方法的参数列中多了一个BitmapFacotry.Options参数。那么BitmapFacotry.Options是干嘛的呢?
举个例子,我们为了缩放图像想要获取该图像的大小,那么首先要在代码中获取这个图像的Bitmap对象,然后通过Bitmap.getWidth()和getheight()方法来获取图像的大小。但是如果想要获取一个大图像的大小,在得到Bitmap对象时会造成oom。这时我们就可以用到BitmapFractory.Options对象的inJustDecodeBounds字段。操作方法:
- 首先获取一个Options对象,并将inJustDecodeBounds设置为True。
- 然后选择一种获取Bitmap途径的方法,并传入Options对象。此时该方法返回的Bitmap为null。
- 然后通过Options.outWidth和outHeight来获取院士图片的大小
- 通过设置Options.inSampleSize来决定获取Bitmap时缩小图像长宽的系数。
- 最后我们把Options实例的inJustDecodeBounds设置为false,并通过该实例获取大图像的Bitmap。这样就防止了OOM
BitmapFactory.Options类有一个参数inSampleSize,该参数为int型,他的值指示了在解析图片为Bitmap时在长宽两个方向上像素缩小的倍数。inSampleSize的默认值和最小值为1(当小于1时,解码器将该值当做1来处理),且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。参考博文高效使用Bitmaps(一) 大Bitmap的加载,BitmapFactory.Options详解
Bitmap常用方法
- public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream) 将位图的压缩到指定的OutputStream,可以理解成将Bitmap保存到文件中!
- format:格式,PNG,JPG等;
- quality:压缩质量,0-100,0表示最低画质压缩,100最大质量(PNG无损,会忽略品质设定)
- stream:输出流
- 返回值代表是否成功压缩到指定流!
- void recycle():回收位图占用的内存空间,把位图标记为Dead
- boolean isRecycled():判断位图内存是否已释放
- int getWidth():获取位图的宽度
- int getHeight():获取位图的高度
- boolean isMutable():图片是否可修改
- int getScaledWidth(Canvas canvas):获取指定密度转换后的图像的宽度
- int getScaledHeight(Canvas canvas):获取指定密度转换后的图像的高度
- Bitmap createBitmap(Bitmap src):以src为原图生成不可变得新图像
- Bitmap createScaledBitmap(Bitmap src, int dstWidth,int dstHeight, boolean filter):以src为原图,创建新的图像,指定新图像的高宽以及是否变。
- Bitmap createBitmap(int width, int height, Config config):创建指定格式、大小的位图
- Bitmap createBitmap(Bitmap source, int x, int y, int width, int
height)以source为原图,创建新的图片,指定起始坐标以及新图像的高宽。 - public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter)
BitmapFractory.Options字段
- boolean inJustDecodeBounds——如果设置为true,不获取图片,不分配内存,但会返回图片的高宽度信息。
- int inSampleSize——图片缩放的倍数。如果设为4,则宽和高都为原来的1/4,则图是原来的1/16。
- int outWidth——获取图片的宽度值
- int outHeight——获取图片的高度值
- int inDensity——用于位图的像素压缩比
- int inTargetDensity——用于目标位图的像素压缩比(要生成的位图)
- boolean inScaled——设置为true时进行图片压缩,从inDensity到inTargetDensity。
获取Bitmap实例
从资源中获取位图的方式有两种:通过BitmapDrawable或者BitmapFactory。
BitmapDrawable
Android支持三种格式的位图图像:.png (preferred),.jpg (acceptable), .gif (discouraged)。
括号里的说明,代表这三种格式的图片在Android中的支持情况,.png格式图片优先,.jpg格式也可以,但是效果没有.png好,.gif支持最差。
在构建应用的时候,Bitmap文件可能会被appt工具压缩自动优化为无损图像。例如,一个真彩色PNG,不需要超过256的颜色可以被转换成一个8位PNG和调色板。这将导致一个图像质量相同,但这需要更少的内存。所以要意识到,在drawable目录中图像的二进制文件在构建程序时可以改变。如果你打算读一个图像作为字节流并将它转换成一个位图,把你的图片放在在res /raw/文件夹里,在那里他们不会被优化。参考博文Android Drawable Resource学习(二)、BitmapDrawable和Bitmap
获取BitmapDrawable
- Bitmap file
我们可以直接从res/drawable目录下的图片文件(.jpg,.png,.gif)获取drawable对象,并将其转型为BitmapDrawable
res/drawable目录下的图片文件(.jpg,.png,.gif)编译资源数据类型:指向BitmapDrawable类型的指针。
- XML Bitmap:
一个XML bitmap是一个在XML文件中定义的指向一个bitmap文件的资源。其效果是作为一个原始位图文件的别名,并且可以指定一些额外的属性。<bitmap>是Bitmap XML的根标签,它有很多属性设置,实现平铺、拉伸或保持图片原始大小,也可以指定对齐方式等效果。可以参考博文Android样式的开发:drawable汇总篇。
同样编译资源类型指向BitmapDrawable类型的指针
Drawable向下转型
Resources res=getResources();
Drawable drawable = res.getDrawable(R.drawable.file_name);
//实际上这是一个BitmapDrawable对象
BitmapDrawable bitmapDrawable=(BitmapDrawable)drawable;
//可以在调用getBitmap方法,得到这个位图
Bitmap bitmap=bitmapDrawable.getBitmap();
BitmapDrawable构造方法
InputStream is=res.openRawResource(R.drawable.file_name);
BitmapDrawable bmpDraw=new BitmapDrawable(is);
Bitmap bmp=bmpDraw.getBitmap();
还有其他构造方法,可以查阅官方文档
Bitmap 2 BitmapDrawable
Drawable drawable = new BitmapDrawable(bitmap);
BitmapFactory
通过上述表格中各种途径的静态方法来获取Bitmap
//res/drawable目录下资源id获取
BitmapFactory.decodeResource(res, resId);
//文件路径获取
BitmapFactory.decodeFile(pathName);
//输入流获取
BitmapFactory.decodeStream(inputStream);
字节流
从字节流获取Bitmap
public Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
Bitmap转换为字节流
public byte[] Bitmap2Bytes(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
Bitmap.Config
在Bitmap类里createBitmap(intwidth, int height, Bitmap.Config config)方法里有一个参数Bitmap.Config是用来做什么的呢?
要解决Bitmap的OOM问题可以有两种方法:
- 压缩大图片的大小,缩放
- 改变大图片的色彩存储方法
那么Bitmap.Config就是图片存储颜色。在Bitmap.Config文档中我们看到四个枚举变量。
- Bitmap.Config : ALPHA_8, 就是Alpha由8位组成
- Bitmap.Config : ARGB_4444, 就是由4个4位组成即16位,
- Bitmap.Config : ARGB_8888, 就是由4个8位组成即32位,
- Bitmap.Config : RGB_565, 就是R为5位,G为6位,B为5位共16位
ARGB指的是一种色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue,其实所有的可见色都是右红绿蓝组成的,所以红绿蓝又称为三原色,每个原色都存储着所表示颜色的信息值。位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真。
Bitmap缩放
public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
int inSampleSize = 1;
if(srcHeight > destHeight || srcWidth > destWidth) {
if(srcWidth > srcHeight) {
inSampleSize = Math.round(srcHeight / destHeight);
} else {
inSampleSize = Math.round(srcWidth /destWidth);
}
}
options = new BitmapFactory.Options();
options.inSampleSize = inSampleSize;
return BitmapFactory.decodeFile(path, options);
}
参考
android图片压缩质量参数Bitmap.Config RGB_565等的含义
Android基础入门教程——8.2.1 Bitmap(位图)详解
高效使用Bitmaps(一) 大Bitmap的加载,BitmapFactory.Options详解
【Android】Drawable、Bitmap、Canvas、Paint之间区别
目标
- 图片的两种解决OOM问题