首先,我阅读了许多关于内存不足异常的帖子和文章,但没有一个对我的情况有所帮助。我要做的是从SD卡加载图像,但将其缩放到精确的像素大小。
我首先得到图像的宽度和高度并计算样本大小:
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(backgroundPath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, getWidth(), getHeight());
以下是我获取样本量的方法(尽管它并不相关):
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
// NOTE: we could use Math.floor here for potential better image quality
// however, this also results in more out of memory issues
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)reqHeight);
} else {
inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}
现在我有一个样本大小,我将图像从磁盘加载到一个近似大小(样本大小):
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
options.inPurgeable = true;
Bitmap bmp = BitmapFactory.decodeFile(backgroundPath, options);
现在,我将我创建的这个位图缩放到我需要的确切大小并清理:
// scale the bitmap to the exact size we need
Bitmap editedBmp = Bitmap.createScaledBitmap(bmp, (int) (width * scaleFactor), (int) (height * scaleFactor), true);
// clean up first bitmap
bmp.recycle();
bmp = null;
System.gc(); // I know you shouldnt do this, but I'm desperate
以上步骤通常会让我的内存异常异常。有没有人知道从磁盘加载精确大小的位图的方法,以避免像上面那样创建两个单独的位图?
此外,当用户第二次运行此代码(设置新图像)时,似乎会出现更多异常。但是,我确保卸载从位图创建的drawable,它允许在再次运行此代码之前对其进行垃圾回收。
有什么建议吗?
谢谢, 尼克
答案 0 :(得分:2)
在您的情况下,执行第一次解码后无需创建中间位图。由于您正在绘制到Canvas,您可以使用以下方法(无论哪种方法最方便)将图像缩放到完美尺寸。
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
答案 1 :(得分:0)
也许这种方法会有所帮助,我想我自己将它从stackoverflow中删除了。它解决了我的内存异常问题。
private Bitmap decodeFile(File f){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=250;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}