Android 图片解码海量内存消耗
Android image decoding massive memory consumption
我想在上传前 compress/re-scale 图片。这是我用于压缩的代码。它适用于非常大的图像,但这 particular image ate up a huge amount of RAM。我已经链接了必要的图像。这是我使用的代码。
我不得不强行调用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;
}
也许只是关注 the tip of the Official Training?
private void setPic() {
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
这部分有一个愚蠢的错误:
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;
}
}
应该是这样的:
if (height > width) {
if (height > sideLength) {
reqHeight = sideLength;
reqWidth = (width * sideLength) / height;
}
inDensity = height;
inTargetDensity = reqHeight;
} else if (width > height) {
if (width > sideLength) {
reqWidth = sideLength;
reqHeight = (height * sideLength) / width;
}
inDensity = width;
inTargetDensity = reqWidth;
}
因为这个调整甚至没有发生!
我想在上传前 compress/re-scale 图片。这是我用于压缩的代码。它适用于非常大的图像,但这 particular image ate up a huge amount of RAM。我已经链接了必要的图像。这是我使用的代码。
我不得不强行调用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;
}
也许只是关注 the tip of the Official Training?
private void setPic() {
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
这部分有一个愚蠢的错误:
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;
}
}
应该是这样的:
if (height > width) {
if (height > sideLength) {
reqHeight = sideLength;
reqWidth = (width * sideLength) / height;
}
inDensity = height;
inTargetDensity = reqHeight;
} else if (width > height) {
if (width > sideLength) {
reqWidth = sideLength;
reqHeight = (height * sideLength) / width;
}
inDensity = width;
inTargetDensity = reqWidth;
}
因为这个调整甚至没有发生!