Я хотел сжать/перемасштабировать изображение перед загрузкой. Вот код, который я использую для сжатия. Он отлично подходит для очень больших изображений, но этот particular image съел huge amount of RAM. Я связал необходимые изображения. Вот код, который я использую.Android-декодирование огромного объема памяти
Мне пришлось принудительно вызвать System.gc(), чтобы освободить слишком часто используемую память.
public static File compressImage(File image) throws IOException {
// Decode just the boundaries
final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
mBitmapOptions.inJustDecodeBounds = true;
final FileInputStream fileInputStream = new FileInputStream(image);
final Bitmap temporary = BitmapFactory.decodeStream(fileInputStream, null, mBitmapOptions);
if (temporary != null)
temporary.recycle();
// Calculate inSampleSize
// Raw height and width of image
final int height = mBitmapOptions.outHeight;
final int width = mBitmapOptions.outWidth;
final int sideLength = 800;
closeQuietly(fileInputStream);
int reqHeight = height;
int reqWidth = width;
final int inDensity;
final int inTargetDensity;
if (height > width) {
inDensity = height;
inTargetDensity = reqHeight;
if (height > sideLength) {
reqHeight = sideLength;
reqWidth = (width * sideLength)/height;
}
} else if (width > height) {
inDensity = width;
inTargetDensity = reqWidth;
if (width > sideLength) {
reqWidth = sideLength;
reqHeight = (height * sideLength)/width;
}
} else {
reqWidth = sideLength;
reqHeight = sideLength;
inDensity = height;
inTargetDensity = reqHeight;
}
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height/2;
final int halfWidth = width/2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight/inSampleSize) > reqHeight && (halfWidth/inSampleSize) > reqWidth)
inSampleSize *= 2;
}
//now go resize the image to the size you want
mBitmapOptions.inSampleSize = inSampleSize;
mBitmapOptions.inDither = true;
mBitmapOptions.inPreferQualityOverSpeed = true;
mBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
mBitmapOptions.inJustDecodeBounds = false;
mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = inDensity;
mBitmapOptions.inTargetDensity = inTargetDensity * mBitmapOptions.inSampleSize;
final File tempFile = File.createTempFile("compressed_profile_photo", null);
final FileInputStream fInputStream = new FileInputStream(image);
final FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
// will load & resize the image to be 1/inSampleSize dimensions
final Bitmap bitmap = BitmapFactory.decodeStream(fInputStream, null, mBitmapOptions);
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fileOutputStream);
fileOutputStream.flush();
bitmap.recycle();
closeQuietly(fInputStream, fileOutputStream);
//noinspection ResultOfMethodCallIgnored
image.delete();
return tempFile;
}
Изображение, на которое вы ссылаетесь, составляет 4208x5198 и будет принимать 4208 * 5198 * 2 = 41,7 МБ в формате RGB_565 только для отдельных пиксельных данных. Ваша диаграмма потребления памяти выглядит примерно так, поэтому вы получаете полноразмерное растровое изображение. Вызов 'System.gc()' может высвободить память раньше, но при вызове его вручную мало смысла, поскольку он будет отброшен в следующий раз, когда GC почувствует, что ему нужно (если у вас нет каких-либо требований в реальном времени и необходимо управлять сроками ГХ). – fadden
Я попробовал изображение, которое в два раза превышает разрешение изображения, которое я связал, потребление памяти не было всплесками вообще. Вряд ли 5-10 mbs дополнительно. – Dexter
Вы можете использовать трекер распределения DDMS (https://developer.android.com/tools/performance/allocation-tracker/index.html), чтобы точно определить, что выделяется, и откуда. – fadden