Problem With Big Images ( Java.lang.outofmemoryerror: Bitmap Size Exceeds Vm Budget )
as a many people i have a problem with big images too. ok,here my code. I found on stackoverflow how to fix this using BitmapFactory.Options. But in my situations i get image no
Solution 1:
since you are getting image from camera,get the uri of the image you capture in onActivityResult() method as follows
Uri selectedImageUri=intent.getData();
String actualPath=getRealPathFromURI(selectedImageUri);
File file=newFile(actualPath);
Bitmap bitmap=decodeFile(file); //this is new bitmap which you can use for your purpose public String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursorcursor= managedQuery(contentUri, proj, null, null, null);
intcolumn_index= cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
private Bitmap decodeFile(File f){
try {
//Decode image size
BitmapFactory.Optionso=newBitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(newFileInputStream(f),null,o);
//The new size we want to scale tofinalint REQUIRED_SIZE=70;
//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.Optionso2=newBitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(newFileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
returnnull;
}
Hope this helps.This is the very familiar problem when u deal with high quality images taken from phone.check this out too
Solution 2:
Here is my BitmpaHelper class that if OutOfMemoryError proof :-)
import java.io.File;
import java.io.FileInputStream;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
publicclassBitmapHelper
{
//decodes image and scales it to reduce memory consumptionpublicstatic Bitmap decodeFile(File bitmapFile, int requiredWidth, int requiredHeight, boolean quickAndDirty)
{
try
{
//Decode image size
BitmapFactory.OptionsbitmapSizeOptions=newBitmapFactory.Options();
bitmapSizeOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(newFileInputStream(bitmapFile), null, bitmapSizeOptions);
// load image using inSampleSize adapted to required image size
BitmapFactory.OptionsbitmapDecodeOptions=newBitmapFactory.Options();
bitmapDecodeOptions.inTempStorage = newbyte[16 * 1024];
bitmapDecodeOptions.inSampleSize = computeInSampleSize(bitmapSizeOptions, requiredWidth, requiredHeight, false);
bitmapDecodeOptions.inPurgeable = true;
bitmapDecodeOptions.inDither = !quickAndDirty;
bitmapDecodeOptions.inPreferredConfig = quickAndDirty ? Bitmap.Config.RGB_565 : Bitmap.Config.ARGB_8888;
BitmapdecodedBitmap= BitmapFactory.decodeStream(newFileInputStream(bitmapFile), null, bitmapDecodeOptions);
// scale bitmap to mathc required size (and keep aspect ratio)floatsrcWidth= (float) bitmapDecodeOptions.outWidth;
floatsrcHeight= (float) bitmapDecodeOptions.outHeight;
floatdstWidth= (float) requiredWidth;
floatdstHeight= (float) requiredHeight;
floatsrcAspectRatio= srcWidth / srcHeight;
floatdstAspectRatio= dstWidth / dstHeight;
// recycleDecodedBitmap is used to know if we must recycle intermediary 'decodedBitmap'// (DO NOT recycle it right away: wait for end of bitmap manipulation process to avoid// java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@416ee7d8// I do not excatly understand why, but this way it's OKbooleanrecycleDecodedBitmap=false;
BitmapscaledBitmap= decodedBitmap;
if (srcAspectRatio < dstAspectRatio)
{
scaledBitmap = getScaledBitmap(decodedBitmap, (int) dstWidth, (int) (srcHeight * (dstWidth / srcWidth)));
// will recycle recycleDecodedBitmap
recycleDecodedBitmap = true;
}
elseif (srcAspectRatio > dstAspectRatio)
{
scaledBitmap = getScaledBitmap(decodedBitmap, (int) (srcWidth * (dstHeight / srcHeight)), (int) dstHeight);
recycleDecodedBitmap = true;
}
// crop image to match required image sizeintscaledBitmapWidth= scaledBitmap.getWidth();
intscaledBitmapHeight= scaledBitmap.getHeight();
BitmapcroppedBitmap= scaledBitmap;
if (scaledBitmapWidth > requiredWidth)
{
intxOffset= (scaledBitmapWidth - requiredWidth) / 2;
croppedBitmap = Bitmap.createBitmap(scaledBitmap, xOffset, 0, requiredWidth, requiredHeight);
scaledBitmap.recycle();
}
elseif (scaledBitmapHeight > requiredHeight)
{
intyOffset= (scaledBitmapHeight - requiredHeight) / 2;
croppedBitmap = Bitmap.createBitmap(scaledBitmap, 0, yOffset, requiredWidth, requiredHeight);
scaledBitmap.recycle();
}
if (recycleDecodedBitmap)
{
decodedBitmap.recycle();
}
decodedBitmap = null;
scaledBitmap = null;
return croppedBitmap;
}
catch (Exception ex)
{
ex.printStackTrace();
}
returnnull;
}
/**
* compute powerOf2 or exact scale to be used as {@link BitmapFactory.Options#inSampleSize} value (for subSampling)
*
* @param requiredWidth
* @param requiredHeight
* @param powerOf2
* weither we want a power of 2 sclae or not
* @return
*/publicstaticintcomputeInSampleSize(BitmapFactory.Options options, int dstWidth, int dstHeight, boolean powerOf2)
{
intinSampleSize=1;
// Raw height and width of imagefinalintsrcHeight= options.outHeight;
finalintsrcWidth= options.outWidth;
if (powerOf2)
{
//Find the correct scale value. It should be the power of 2.inttmpWidth= srcWidth, tmpHeight = srcHeight;
while (true)
{
if (tmpWidth / 2 < dstWidth || tmpHeight / 2 < dstHeight)
break;
tmpWidth /= 2;
tmpHeight /= 2;
inSampleSize *= 2;
}
}
else
{
// Calculate ratios of height and width to requested height and widthfinalintheightRatio= Math.round((float) srcHeight / (float) dstHeight);
finalintwidthRatio= Math.round((float) srcWidth / (float) dstWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee// a final image with both dimensions larger than or equal to the// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
publicstatic Bitmap drawableToBitmap(Drawable drawable)
{
if (drawable instanceof BitmapDrawable)
{
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmapbitmap= Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvascanvas=newCanvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
publicstatic Bitmap getScaledBitmap(Bitmap bitmap, int newWidth, int newHeight)
{
intwidth= bitmap.getWidth();
intheight= bitmap.getHeight();
floatscaleWidth= ((float) newWidth) / width;
floatscaleHeight= ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATIONMatrixmatrix=newMatrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAPBitmapresizedBitmap= Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
}
Solution 3:
I have same problem in my android app. When you decode a bitmap from a big sized image and set as imageBitmap to an image view probably your application will slow and after a few try you'll get an "out of memory exception"
You can use Universal Image Loader. https://github.com/nostra13/Android-Universal-Image-Loader
Stringurl="file://" + your_file_path_on_sd_card;
com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(url, ivPicture, options);
Post a Comment for "Problem With Big Images ( Java.lang.outofmemoryerror: Bitmap Size Exceeds Vm Budget )"