BitmapFactory.de codeStream出内存尽管使用降低样本量 [英] BitmapFactory.decodeStream out of memory despite using reduced sample size

查看:207
本文介绍了BitmapFactory.de codeStream出内存尽管使用降低样本量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过关于内存分配问题与位图解码很多相关的帖子,但我仍无法使用,甚至在官方网站上提供的code后,找到解决以下问题。

I have read many related posts concerning memory allocation problems with decoding bitmaps, but am still unable to find the solution to the following problem even after using the code provided in the official website.

下面是我的code:

public static Bitmap decodeSampledBitmapFromResource(InputStream inputStream, int reqWidth, int reqHeight) {

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    try {
        while ((len = inputStream.read(buffer)) > -1) {
        baos.write(buffer, 0, len);
        }
        baos.flush();
        InputStream is1 = new ByteArrayInputStream(baos.toByteArray());
        InputStream is2 = new ByteArrayInputStream(baos.toByteArray());

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(is1, null, options);

        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeStream(is2, null, options);

    } catch (Exception e) {
        e.printStackTrace();

        return null;
    }
}

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) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

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

bitmap = decodeSampledBitmapFromResource(inputStream, 600, 600); 

我收到内存不足错误在3250016 - 字节分配在这一行:

I am getting "Out of memory error on a 3250016 - byte allocation" in this line:

return BitmapFactory.decodeStream(is2, null, options);

这似乎对我来说,3.2 MB小到足以进行分配。我在哪里的问题呢?我该如何解决这个问题?

It would seem to me that 3.2 MB is small enough to be allocated. Where am I going wrong? How can I solve this?

修改

在寻找这个解决方案<一href="http://stackoverflow.com/questions/10314527/caused-by-java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget/10408877#10408877">HERE用N-喜悦正常工作所需尺寸300,但我需要的尺寸是800,所以我仍然得到错误。

After looking into this solution HERE by N-Joy it works fine with Required size 300 but my required size is 800, so i am still getting the error.

推荐答案

该方法的 德codeSampledBitmapFromResource 的不是记忆效率,因为它使用3个流:在ByteArrayOutputStream BAOS,ByteArrayInputStream的IS1和ByteArrayInputStream的IS2,其中每个形象店的相同数据流(一个字节数组每个)

The method decodeSampledBitmapFromResource is not memory efficient because it uses 3 streams: the ByteArrayOutputStream baos, ByteArrayInputStream is1 and ByteArrayInputStream is2, each of those stores the same stream data of the image (one byte array for each).

当我与我的设备(LG承上启下4)脱code SD卡上的2560×1600图像测试的目标规模800它需要是这样的:

And when I test with my device (LG nexus 4) to decode an 2560x1600 image on SDcard to target size 800 it takes something like this:

03-13 15:47:52.557: E/DecodeBitmap(11177): dalvikPss (beginning) = 1780
03-13 15:47:53.157: E/DecodeBitmap(11177): dalvikPss (decoding) = 26393
03-13 15:47:53.548: E/DecodeBitmap(11177): dalvikPss (after all) = 30401 time = 999

我们可以看到:太多内存分配(28.5 MB)刚刚去code 4096000像素图像

We can see: too much memory allocated (28.5 MB) just to decode 4096000 a pixel image.

解决方案:我们读InputStream和直接将数据存储到一个字节数组,并使用此字节数组,其余的工作。
样品code:

Solution: we read the InputStream and store the data directly into one byte array and use this byte array for the rest work.
Sample code:

public Bitmap decodeSampledBitmapFromResourceMemOpt(
            InputStream inputStream, int reqWidth, int reqHeight) {

        byte[] byteArr = new byte[0];
        byte[] buffer = new byte[1024];
        int len;
        int count = 0;

        try {
            while ((len = inputStream.read(buffer)) > -1) {
                if (len != 0) {
                    if (count + len > byteArr.length) {
                        byte[] newbuf = new byte[(count + len) * 2];
                        System.arraycopy(byteArr, 0, newbuf, 0, count);
                        byteArr = newbuf;
                    }

                    System.arraycopy(buffer, 0, byteArr, count, len);
                    count += len;
                }
            }

            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(byteArr, 0, count, options);

            options.inSampleSize = calculateInSampleSize(options, reqWidth,
                    reqHeight);
            options.inPurgeable = true;
            options.inInputShareable = true;
            options.inJustDecodeBounds = false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;

            int[] pids = { android.os.Process.myPid() };
            MemoryInfo myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
            Log.e(TAG, "dalvikPss (decoding) = " + myMemInfo.dalvikPss);

            return BitmapFactory.decodeByteArray(byteArr, 0, count, options);

        } catch (Exception e) {
            e.printStackTrace();

            return null;
        }
    }

这是不计算的方法:

public void onButtonClicked(View v) {
        int[] pids = { android.os.Process.myPid() };
        MemoryInfo myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
        Log.e(TAG, "dalvikPss (beginning) = " + myMemInfo.dalvikPss);

        long startTime = System.currentTimeMillis();

        FileInputStream inputStream;
        String filePath = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "/test2.png";
        File file = new File(filePath);
        try {
            inputStream = new FileInputStream(file);
//          mBitmap = decodeSampledBitmapFromResource(inputStream, 800, 800);
            mBitmap = decodeSampledBitmapFromResourceMemOpt(inputStream, 800,
                    800);
            ImageView imageView = (ImageView) findViewById(R.id.image);
            imageView.setImageBitmap(mBitmap);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
        Log.e(TAG, "dalvikPss (after all) = " + myMemInfo.dalvikPss
                + " time = " + (System.currentTimeMillis() - startTime));
    }

和结果:

03-13 16:02:20.373: E/DecodeBitmap(13663): dalvikPss (beginning) = 1823
03-13 16:02:20.923: E/DecodeBitmap(13663): dalvikPss (decoding) = 18414
03-13 16:02:21.294: E/DecodeBitmap(13663): dalvikPss (after all) = 18414 time = 917

这篇关于BitmapFactory.de codeStream出内存尽管使用降低样本量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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