在下面的代码中,我得到异常"字节分配时内存不足"对于函数中的大尺寸图像" getScaledBitmap"在代码中第二次处理decodeFile时。由于我正在屏幕上处理4个不同的图像,所以下面这个函数被调用了4次。
请指导一下。
private Bitmap processimage(String picturePath){
Bitmap thumbnail =null;
thumbnail=getScaledBitmap(picturePath,500,500);
Matrix matrix = null;
try {
ExifInterface exif = new ExifInterface(picturePath);
int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotationInDegrees = bal.exifToDegrees(rotation);
matrix = new Matrix();
if (rotation != 0f) {
matrix.preRotate(rotationInDegrees);
thumbnail=Bitmap.createBitmap(thumbnail, 0,0, thumbnail.getWidth(), thumbnail.getHeight(), matrix, true);
}
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
return thumbnail;
}
protected Bitmap getScaledBitmap(String picturePath, int width, int height) {
Bitmap result=null;
try{
BitmapFactory.Options sizeOptions = new BitmapFactory.Options();
sizeOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(picturePath, sizeOptions);
int inSampleSize = calculateInSampleSize(sizeOptions, width, height);
sizeOptions.inJustDecodeBounds = false;
sizeOptions.inSampleSize = inSampleSize;
result=BitmapFactory.decodeFile(picturePath, sizeOptions);
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
protected int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) > reqHeight
|| (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public int exifToDegrees(int exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { return 180; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { return 270; }
return 0;
}
答案 0 :(得分:0)
to scale image and to catch oom error I use the following code(but for one image).I am not sure if it will be ok for you..and include try catch for OOM in your code to avoid crash
Options options = new BitmapFactory.Options();
try{
options.inScaled = false;
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
imgBitmap=decodeFile(file);
}
catch(OutOfMemoryError e){
System.out.println("out of memory");
flag=1;
System.out.println("clearing bitmap????????????");
if (imgBitmap!=null) {
this.setBackgroundResource(0);
this.clearAnimation();
imgBitmap.recycle();
imgBitmap = null;}
// }
}
优化图像文件的方法
public Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
o.inDither=false; //Disable Dithering mode
o.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
o.inInputShareable=true;
o.inPreferredConfig = Bitmap.Config.ARGB_8888;
//Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
o.inTempStorage=new byte[16*1024];
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// Find the correct scale value. It should be the power of 2.
int REQUIRED_SIZE = 300;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
if(REQUIRED_SIZE > width_tmp)
REQUIRED_SIZE = width_tmp;
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;
System.out.println(scale+"______________________________-");
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inDither=false;
o2.inScaled = false;
o2.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
o2.inInputShareable=true;
//Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
o2.inTempStorage=new byte[24*1024];
o2.inSampleSize = 2;
o2.outWidth = width_tmp;
o2.outHeight = height_tmp;
o2.inPreferredConfig = Bitmap.Config.ARGB_8888;
try {
BitmapFactory.Options.class.getField("inNativeAlloc").setBoolean(o2,true);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
o2.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(new FileInputStream(f), null,
o2);
}
catch (FileNotFoundException e) {
System.out.println("file not found");
}
return null;
}
答案 1 :(得分:0)
在许多手机上,一个应用程序有足够的RAM用于准确的1(一)个图像,加载第二个图像总是会导致内存不足异常。即使您可以在手机的RAM中加载2张照片,另一部手机也会有更好的相机,但它会失败。如果要在屏幕上显示大图像,则必须缩放它们。
如果你想要合并两个大图像,那么,你有问题。我建议在一个单独的进程(命令行工具或服务)中执行此操作。请注意,应用程序可以在清单中请求大堆:android:largeHeap=["true" | "false"]
(link)。但最有可能的是你可以避免在RAM中加载两个图像。