这是我想出的,基于从旧 Android 版本中删除的裁剪库中名为 getBitmap() 的方法。我做了一些修改:
private Bitmap getBitmap(Uri uri, int width, int height) {
InputStream in = null;
try {
int IMAGE_MAX_SIZE = Math.max(width, height);
in = getContentResolver().openInputStream(uri);
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int scale = 1;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
//adjust sample size such that the image is bigger than the result
scale -= 1;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
in = getContentResolver().openInputStream(uri);
Bitmap b = BitmapFactory.decodeStream(in, null, o2);
in.close();
//scale bitmap to desired size
Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, width, height, false);
//free memory
b.recycle();
return scaledBitmap;
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
return null;
}
这样做是使用 BitmapFactory.Options() + 一些样本大小加载位图 - 这样原始图像不会加载到内存中。问题是样本量只能分步进行。我使用我复制的一些数学来获得图像的“最小”样本大小 - 并减去 1 以获得将产生最小值的样本大小。位图大于我需要的大小。
然后为了获得与所要求的大小完全相同的位图,使用Bitmap.createScaledBitmap(b, width, height, false);
. 并立即回收更大的位图。这很重要,因为例如,在我的例子中,为了获得 480 x 800 位图,较大的位图是 1280 x 960,占用 4.6mb 内存。
A more memory friendly way would be to not adjust scale
, so a smaller bitmap will be scaled up to match the required size. But this will reduce the quality of the image.