BitmapFactory.decodeByteArray OutOfMemory

Posted

技术标签:

【中文标题】BitmapFactory.decodeByteArray OutOfMemory【英文标题】: 【发布时间】:2015-10-01 23:08:18 【问题描述】:

我正在尝试从Camera.PictureCallback onPictureTaken 获取 Jpeg,但是当我这样做时

bitmapImage = BitmapFactory.decodeByteArray(data, 0, data.length);

这是第一次出现在 logcat 上:

将堆(碎片情况)增加到 48.886MB 以分配 15728656 字节

当我尝试重新拍照时,应用程序崩溃并显示此堆栈跟踪:

java.lang.OutOfMemoryError
            at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
            at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:603)
            at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:626)
            at com.delsorboilario.brianzashop.Scatta$5.onPictureTaken(Scatta.java:216)
            at android.hardware.Camera$EventHandler.handleMessage(Camera.java:987)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5511)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

这是代码:

android.hardware.Camera.PictureCallback jpegCallback = new android.hardware.Camera.PictureCallback() 
    @Override
    public void onPictureTaken(byte[] data, android.hardware.Camera camera) 

         bitmapImage = BitmapFactory.decodeByteArray(data, 0, data.length);


        Uri tempUri = getImageUri(getApplicationContext(), bitmapImage);

        File finalFile = new File(getRealPathFromURI(tempUri));

        System.out.println("aaaaaa "+finalFile);


    
;

编辑

按照 MicheleLacorte 的建议,我尝试在拍摄后回收位图 File finalFile

没关系,但是当我尝试从该路径显示图像时,我遇到了同样的错误。

【问题讨论】:

你在使用 Android Studio 吗? 我也遇到过类似的问题,建议你阅读这里***.com/questions/18723755/…,一旦不再需要,就用Bitmap.recycle()尝试“销毁”位图;或位图=空; (糟糕的选择) 【参考方案1】:

在 Android 中加载大型位图确实很困难 看看这个

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

【讨论】:

谢谢你的建议,你能给我一个具体的例子吗?谢谢【参考方案2】:

在http://developer.android.com/training/displaying-bitmaps/load-bitmap.html 之后,我只是更改了 decodeSampledBitmapFromResource 静态方法以适应 decodeByteArray 而不是 decodeResource。我把这些方法放在我的 util 类中。

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) 
    // Raw height and width of image
    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;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) 
            inSampleSize *= 2;
        
    

    return inSampleSize;
    

public static Bitmap decodeSampledBitmapFromResource(byte[] data, int   reqWidth, int reqHeight) 

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    //options.inPurgeable = true; 
    BitmapFactory.decodeByteArray(data, 0, data.length, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeByteArray(data, 0, data.length, options);

然后用你的代码试试这个:

android.hardware.Camera.PictureCallback jpegCallback = new  android.hardware.Camera.PictureCallback() 
@Override
public void onPictureTaken(byte[] data, android.hardware.Camera camera) 

     //bitmapImage = BitmapFactory.decodeByteArray(data, 0, data.length);
     // Utils is my utility class
     bitmapImage = Utils.decodeSampledBitmapFromResource(data, 50,50);


    Uri tempUri = getImageUri(getApplicationContext(), bitmapImage);

    File finalFile = new File(getRealPathFromURI(tempUri));

    System.out.println("aaaaaa "+finalFile);



;

【讨论】:

【参考方案3】:

你说当你拍第二张照片时你有问题?在允许用户重新拍摄照片之前,您需要对第一张照片做一些事情以清理一些内存。如果您不打算继续显示它,请将其保存到磁盘上的缓存文件中,然后使用

释放内存资源
bitmapImage.recycle();
bitmapImage = null;

如果您确实需要让它显示在屏幕上,请尽可能对其进行缩减采样,但不要让它看起来很糟糕,并确保您没有引用原始全尺寸图像。还要看看你是否可以在从字节数组中获取图像时对图像进行一些压缩。

【讨论】:

以上是关于BitmapFactory.decodeByteArray OutOfMemory的主要内容,如果未能解决你的问题,请参考以下文章