Bitmap的构造方法的修饰符是default的,意味着无法直接通过构造方法实例化Bitmap。
Android中提供了BitmapFactory来实例化Bitmap。BitmapFactory提供了多个decodeXXX方法供从不同来源加载图片资源并解析成Bitmap。主要方法如下图所示:
下面以decodeResource与decodeByteArray为例来看加载并解析Bitmap
val bitmap = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)
val bytes = assets.open("pic.jpg").readBytes()
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
Bitmap中提供了众多重载的静态方法createBitmap来创建Bitmap。主要如下图所示:
这些方法大致可以分为三类:
/**
* 通过矩阵的方式,返回原始 Bitmap 中的一个不可变子集。新 Bitmap 可能返回的就是原始的 Bitmap,也可能还是复制出来的。
* 新 Bitmap 与原始 Bitmap 具有相同的密度(density)和颜色空间;
*
* @param source 原始 Bitmap
* @param x 在原始 Bitmap 中 x方向的其起始坐标(你可能只需要原始 Bitmap x方向上的一部分)
* @param y 在原始 Bitmap 中 y方向的其起始坐标(你可能只需要原始 Bitmap y方向上的一部分)
* @param width 需要返回 Bitmap 的宽度(px)(如果超过原始Bitmap宽度会报错)
* @param height 需要返回 Bitmap 的高度(px)(如果超过原始Bitmap高度会报错)
* @param m Matrix类型,表示需要做的变换操作
* @param filter 是否需要过滤,只有 matrix 变换不只有平移操作才有效
*/
public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height,
@Nullable Matrix m, boolean filter) {
}
/**
*
* 返回具有指定宽度和高度的不可变位图,每个像素值设置为colors数组中的对应值。
* 其初始密度由给定的确定DisplayMetrics。新创建的位图位于sRGB 颜色空间中。
* @param display 显示将显示此位图的显示的度量标准
* @param colors 用于初始化像素的sRGB数组
* @param offset 颜色数组中第一个颜色之前要跳过的值的数量
* @param stride 行之间数组中的颜色数(必须> = width或<= -width)
* @param width 位图的宽度
* @param height 位图的高度
* @param config 要创建的位图配置。如果配置不支持每像素alpha(例如RGB_565),
* 那么colors []中的alpha字节将被忽略(假设为FF)
*/
public static Bitmap createBitmap(@NonNull DisplayMetrics display,
@NonNull @ColorInt int[] colors, int offset, int stride,
int width, int height, @NonNull Config config) {
}
/**
* 对Bitmap进行缩放,缩放成宽 dstWidth、高 dstHeight 的新Bitmap
*/
public static Bitmap createScaledBitmap(@NonNull Bitmap src, int dstWidth, int dstHeight,boolean filter) {
}
使用BitmapFactory时经常会用到Options这个静态内部类。它内部有很多比较重要的属性。如下:
BitmapFactory.Options的使用
val options = BitmapFactory.Options()
options.inPreferredConfig = Bitmap.Config.RGB_565 // 设置bitmap的颜色格式
options.inSampleSize = 2 // 设置采样率
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.image, options)
质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,图片的长,宽,像素都不会改变,那么bitmap所占内存大小是不会变的。
我们可以看到有个参数:quality,可以调节你压缩的比例,但是还要注意一点就是,质量压缩对png格式这种图片没有作用,因为png是无损压缩。
private void compressQuality() {
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test);
mSrcSize = bm.getByteCount() + "byte";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] bytes = bos.toByteArray();
mSrcBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
这个方法主要用图片分辨率较大,但是设置的目标View较小时进行的。可以通过采样压缩将图片分辨率压缩到View的宽高相等。由于图片的分辨率减小,所有图片加载到内存时占用的空间也会更小。代码如下:
BitmapFactory.Options options = new Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId, options);
可以通过矩阵来缩放图片的尺寸达到压缩图片的效果,与采样压缩原理一样。
private void compressMatrix() {
Matrix matrix = new Matrix();
matrix.setScale(0.5f, 0.5f);
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test);
mSrcBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
bm = null;
}
通过inPreferredConfig的配置,修改单个像素点占用的内存来实现压缩。如在包含透明通道的图片中可以将inPreferredConfig设置为RGB_565,相比RGB_8888节省一半的内存开销。
内容来源: