Во-первых, я прочитал много сообщений и статей об исключениях из памяти, но ни один из них не помог мне в моей ситуации. То, что я пытаюсь сделать, это загрузить изображение с 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
Вышеупомянутый шаг обычно вызывает исключение из памяти. Кто-нибудь знает способ загрузки растрового изображения точного размера с диска, чтобы избежать необходимости создавать два отдельных растровых изображения, например, выше?
Кроме того, похоже, что больше исключений возникает, когда пользователь запускает этот код во второй раз (устанавливает новое изображение). Тем не менее, я не забываю выгружать извлекаемый, который был создан из растрового изображения, что позволяет ему собирать мусор, прежде чем этот код будет запущен снова.
Какие-либо предложения?
Спасибо, Ник
В вашем случае нет необходимости создавать промежуточное растровое изображение после того, как вы выполнили первый декодирование. Поскольку вы рисуете на холсте, вы можете использовать либо следующие методы (в зависимости от того, что вам удобнее всего), чтобы масштабировать изображение до идеального размера.
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
Может быть, этот метод был бы полезен, я думаю, что сам отвлек его от 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;
}
editedBmp
,editedBmp
его ширину и высоту, а также scaleFactor, чтобы убедиться, что ваши параметры верны.