用于大图像的Android OutOfMemoryError

时间:2014-04-11 09:38:45

标签: java android

该方法为大图像(不是分辨率)抛出OutOfMemoryError 我有12张MP照片,它们的大小各不相同(1.5MB,2.5MB,3.2MB,4.1MB)等等,所有这些照片的分辨率都是4000 x 3000(像素)。

缩放器方法适用于尺寸小于3MB的图像,但对于那些大于3MB的图像,它会抛出OutOfMemoryError我不知道可以解决什么问题,我的应用程序主要是用于调整大图像的大小,这真的得到了我无处可去。

缩放器方法是:

public File resizeBitmap(String imPath, int reqSize) {
    File fl = null;
    try{

    // First decode with inJustDecodeBounds=true to check dimensions

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;

    BitmapFactory.decodeFile(imPath, options);

    // Calculate inSampleSize

    options.inSampleSize = calculateInSampleSize(options, reqSize);

    // Decode bitmap with inSampleSize set

    options.inJustDecodeBounds = false;
    Bitmap saveImg = BitmapFactory.decodeFile(imPath, options);

    //save resized image
    String tmpName = "IMG_"+String.valueOf(System.currentTimeMillis()) + ".jpg";
    fl = fileCache.getRawFile(tmpName);
    FileOutputStream fos = new FileOutputStream(fl);
    saveImg.compress(Bitmap.CompressFormat.JPEG, 95, fos);
    saveImg.recycle();


    return fl;
}
catch (Throwable eex){
    eex.printStackTrace();
    if(eex instanceof OutOfMemoryError) {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(Resizer.this, "Memory ran out", Toast.LENGTH_SHORT).show();
            }
        });
    }
    return null;
 }
}
//Method for calculating insamplesize
public int calculateInSampleSize(BitmapFactory.Options options, int reqSize) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
Log.i("width",""+width);
Log.i("height",""+height);
int inSampleSize = 1;

if (height > reqSize || width > reqSize) {

        if (width > height) {
            inSampleSize = Math.round((float) height / (float) reqSize);
        } else {
            inSampleSize = Math.round((float) width / (float) reqSize);
         }


}

return inSampleSize;

}

//Stacktrace
04-11 09:01:19.832: W/System.err(8832): java.lang.OutOfMemoryError
04-11 09:01:19.953: W/System.err(8832):     at  android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
04-11 09:01:19.972: W/System.err(8832):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:529)
04-11 09:01:19.993: W/System.err(8832):     at com.scale.app.Resizer.resizeBitmap(Resizer.java:1290)

3 个答案:

答案 0 :(得分:1)

<强> Read Article

图像尺寸:4000 * 3000 in px

图像加载时:4000 * 3000 * 4 =? KB

因此,Android设备的Vitrual堆内存为:32 MB,64 MB,128 MB ......等等

如果您使用:

<application

    android:largeHeap="true">

</application>

这将增加VHM双倍(如果32 MB = 2 * 32 MB)。这不是一个很好的方法来做到这一点,影响操作系统

您需要减小图像的大小。


使用下面的类并传递图像的路径和宽度,高度你想要的

  
    
      
        

Bitmap bitmap = BitmapSize.getDecodedBitmap(path,400,400);

      
    
  

类::::

public class BitmapSize{



public static Bitmap getDecodedBitmap(String path, float target_width, float target_height) {
    Bitmap outBitmap = null;
    try {
        Options decode_options = new Options();
        decode_options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path,decode_options);  //This will just fill the output parameters
        int inSampleSize = calculateInSampleSize(decode_options, target_width, target_height);

        Options outOptions = new Options();
        outOptions.inJustDecodeBounds = false;
        outOptions.inSampleSize = inSampleSize;
        outOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
        outOptions.inScaled = false;

        Bitmap decodedBitmap = BitmapFactory.decodeFile(path,outOptions);
        outBitmap = Bitmap.createScaledBitmap(decodedBitmap,// (int)target_width, (int)target_height, true);
                (int)((float)decodedBitmap.getWidth() / inSampleSize),
                (int)((float)decodedBitmap.getHeight() / inSampleSize), true);
        System.out.println("Decoded Bitmap: Width "  + outBitmap.getWidth() + " Height = " + outBitmap.getHeight() + " inSampleSize = " + inSampleSize);

    } catch (Exception e) {
        // TODO: handle exception
    }

    return outBitmap;
}

public static int calculateInSampleSize(Options options, float reqWidth, float reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}

}

答案 1 :(得分:0)

请尝试使用这些选项属性..

    BitmapFactory.Options opts=new BitmapFactory.Options();
    opts.inDither=false;                     //Disable Dithering mode
    opts.inPurgeable=true;                   //Tell to gc that whether it needs free memory, the Bitmap can be cleared
    opts.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
    opts.inTempStorage=new byte[32 * 1024];
    opts.inSampleSize = 1;

要降低图像文件的质量,请增加 opts.inSampleSize的数量。 Click here for more details

在应用程序标记

中的Manifest.xml中再添加一个属性
  

机器人:largeHeap =&#34;真&#34;

答案 2 :(得分:0)

请阅读http://developer.android.com/training/displaying-bitmaps/load-bitmap.html如何处理大型位图。

  

BitmapFactory类提供了几种解码方法   (decodeByteArray(),decodeFile(),decodeResource()等)用于创建   来自各种来源的位图。选择最合适的解码   基于图像数据源的方法。这些方法试图   为构造的位图分配内存,因此很容易   导致OutOfMemory异常