安卓的OutOfMemoryError对于大图片 [英] Android OutOfMemoryError for large images

查看:109
本文介绍了安卓的OutOfMemoryError对于大图片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该方法抛出的OutOfMemoryError对于大图像尺寸(不分辨率) 我有1200万像素的照片,所有的人都在不同的大小(1.5MB,2.5MB,3.2MB,4.1MB)等以及分辨率为所有的人都是一样的4000 x 3000(像素)。

的大小调整方法,工作正常,图像小于3MB的大小,但是对于那些图像> 3MB它抛出的OutOfMemoryError我不知道什么可以修复它​​,我的应用程序主要是为调整大型图像,这实在是让我没有出路的。

的大小调整的方法是:

 公开文件resizeBitmap(Impath的字符串,诠释reqSize){
    文件F1 = NULL;
    尝试{

    //第一代code与inJustDe codeBounds = true来检查尺寸

    最后BitmapFactory.Options选项=新BitmapFactory.Options();
    options.inJustDe codeBounds = TRUE;

    BitmapFactory.de codeFILE(Impath的,选件);

    //计算inSampleSize

    options.inSampleSize = calculateInSampleSize(选项,reqSize);

    与inSampleSize集//德code位图

    options.inJustDe codeBounds = FALSE;
    位图saveImg = BitmapFactory.de codeFILE(Impath的,选件);

    //保存调整后的图像
    字符串tmpName =IMG _+将String.valueOf(System.currentTimeMillis的())+.JPG;
    FL = fileCache.getRawFile(tmpName);
    FileOutputStream中FOS =新的FileOutputStream(FL);
    saveImg.com preSS(Bitmap.Com pressFormat.JPEG,95,FOS);
    saveImg.recycle();


    返回佛罗里达州;
}
捕获(的Throwable EEX){
    eex.printStackTrace();
    如果(EEX的instanceof的OutOfMemoryError){
        runOnUiThread(新的Runnable(){
            公共无效的run(){
                Toast.makeText(Resizer.this,内存跑了出来,Toast.LENGTH_SHORT).show();
            }
        });
    }
    返回null;
 }
}
//计算insamplesize方法
公众诠释calculateInSampleSize(BitmapFactory.Options选项,INT reqSize){
//原始高度和宽度的图像
最终诠释身高= options.outHeight;
最终诠释宽度= options.outWidth;
Log.i(宽,+宽);
Log.i(高度,+高);
INT inSampleSize = 1;

如果(高度> reqSize ||宽度GT; reqSize){

        如果(宽>高度){
            inSampleSize = Math.round((浮动)的高度/(浮点)reqSize);
        } 其他 {
            inSampleSize = Math.round((浮点)宽/(浮点)reqSize);
         }


}

返回inSampleSize;
 

}

  //堆栈跟踪
9月4日至11号:01:19.832:W / System.err的(8832):java.lang.OutOfMemoryError
9月4日至11号:01:19.953:W / System.err的(8832):在android.graphics.BitmapFactory.nativeDe codeStream(本机方法)
9月4日至11号:01:19.972:W / System.err的(8832):在android.graphics.BitmapFactory.de codeStream(BitmapFactory.java:529)
9月4日至11号:01:19.993:W / System.err的(8832):在com.scale.app.Resizer.resizeBitmap(Resizer.java:1290)
 

解决方案

阅读文章

图片尺寸:4000 * 3000像素

在图像载:4000 * 3000 * 4 =? KB

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

如果您使用的是:

 <应用

    机器人:largeHeap =真正的>

< /用途>
 

这将增加VHM双(如果32 MB = 2 * 32 MB)。但是这将不是一个好办法做到这一点,在OS效果

您需要降低图像的大小。


使用下面的类并把图像和宽度,你想要什么高度

的路径
  
    
      
        

位图位= BitmapSize.getDe codedBitmap(路,400,400);

      
    
  

类::::

 公共类BitmapSize {



公共静态位图getDe codedBitmap(字符串路径,浮TARGET_WIDTH,浮TARGET_HEIGHT){
    位图outBitmap = NULL;
    尝试 {
        选择去code_options =新的选项();
        德code_options.inJustDe codeBounds = TRUE;
        BitmapFactory.de codeFILE(路径,去code_options); //这将只需填写输出参数
        INT inSampleSize = calculateInSampleSize(德code_options,TARGET_WIDTH,TARGET_HEIGHT);

        选项​​outOptions =新的选项();
        outOptions.inJustDe codeBounds = FALSE;
        outOptions.inSampleSize = inSampleSize;
        outOptions.in preferredConfig = Bitmap.Config.ARGB_8888;
        outOptions.inScaled = FALSE;

        位图德codedBitmap = BitmapFactory.de codeFILE(路径,outOptions);
        outBitmap = Bitmap.createScaledBitmap(德codedBitmap,//(INT)TARGET_WIDTH,(INT)TARGET_HEIGHT,真正的);
                (INT)((浮点)去codedBitmap.getWidth()/ inSampleSize)
                (INT)((浮点)去codedBitmap.getHeight()/ inSampleSize),TRUE);
        的System.out.println(德codeD位图:宽度+ outBitmap.getWidth()+高度=+ outBitmap.getHeight()+inSampleSize =+ inSampleSize);

    }赶上(例外五){
        // TODO:处理异常
    }

    返回outBitmap;
}

公共静态INT calculateInSampleSize(选项选项,浮reqWidth,浮reqHeight){
    最终诠释身高= options.outHeight;
    最终诠释宽度= options.outWidth;
    INT inSampleSize = 1;

    如果(高度> reqHeight ||宽度GT; reqWidth){

        最终诠释heightRatio = Math.round((浮点)高度
                /(浮点)reqHeight);
        最终诠释widthRatio = Math.round((浮点)宽/(浮点)reqWidth);

        inSampleSize = heightRatio< widthRatio? heightRatio:widthRatio;
    }

    返回inSampleSize;
}

}
 

The method throws OutOfMemoryError for large images in size( not by resolution) i have 12 MP photos, all of them are different in size(1.5MB, 2.5MB, 3.2MB, 4.1MB) etc and the resolution for all of them are same 4000 x 3000 (pixels).

The resizer method works fine for images less than 3MB in size, but for those images that are >3MB it throws OutOfMemoryError i dont know what could fix it, my app is mainly for resizing large images, and this is really getting me nowhere.

The resizer method is:

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)

解决方案

Read Article

Image Size : 4000*3000 in px

When the image load : 4000*3000*4 = ? KB

So,Vitrual Heap Memory of the Android device are : 32 MB, 64 MB , 128 MB ... so on

if you using:

<application

    android:largeHeap="true">

</application>

This will increase the VHM double (if 32 MB = 2* 32 MB). BUt this will not an good way to do this, effect on OS

You need to decrease the size of the image.


Use the below class and pass the path of the image and width , height what you want

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

Class::::

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;
}

}

这篇关于安卓的OutOfMemoryError对于大图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆