Bitmap size exceeds VM budget in Android
I used the following code in Gallery View
and I got the following exception. Can anyone show me where I am wrong?
07-18 12:45:59.774: WARN/System.err(6758): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
07-18 12:45:59.774: WARN/System.err(6758): at android.graphics.Bitmap.nativeCreate(Native Method)
07-18 12:45:59.774: WARN/System.err(6758): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
07-18 12:45:59.774: WARN/System.err(6758): at android.graphics.Bitmap.createBitmap(Bitmap
My code:
public boolean createReflectedImages() {
//The gap we want between the reflection and the original image
final int reflectionGap = 4;
int index = 0;
for (int imageId : mImageIds) {
try
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
Bitmap originalImage = BitmapFactory.decodeResource(getResources(),
imageId,options);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
//This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
//Create a Bitmap with the flip matrix applied to it.
//We only want the bottom half of the image
reflectionImage = Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);
//Create a new bitmap with same width but taller to fit reflection
bitmapWithReflection = Bitmap.createBitmap(width
, (height + height/2), Config.ARGB_8888);
//Create a new Canvas with the bitmap that's big enough for
//the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
//Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
//Draw开发者_开发问答 in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
//Draw in the reflection
canvas.drawBitmap(reflectionImage,0, height + reflectionGap, null);
//Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
TileMode.CLAMP);
//Set the paint to use this shader (linear gradient)
paint.setShader(shader);
//Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
//Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width,
bitmapWithReflection.getHeight() + reflectionGap, paint);
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(bitmapWithReflection);
imageView.setLayoutParams(new CoverFlow.LayoutParams(200, 280));
imageView.setScaleType(ScaleType.MATRIX);
mImages[index++] = imageView;
}catch(Exception e)
{
e.printStackTrace();
}
}
return true;
}
Chances are the image you are loading is exceeding the RAM limit for your Android application. You should be using inSampleSize
when you load the image in order to scale it down before it hogs all your memory. I use this function to load all my images:
public static Bitmap decodeFile(File file, int size){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inPurgeable = true;
o.inInputShareable = true;
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE = size;
//Find the correct scale value. It should be the power of 2.
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(file), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
There are a couple extra options in there, but the big one for your problem is the inSampleSize
which must be a power of 2. Hope this helps.
精彩评论