【问题标题】:outOfMemory Exception while re-encoding image重新编码图像时出现 outOfMemory 异常
【发布时间】:2014-01-30 17:17:49
【问题描述】:

我正在尝试将图像编码为 64 base ,

从图库中选择图片并尝试保存后,我收到此错误:

内存不足异常

任何人都可以建议如何将此图像设置为 base 64 而不会出现内存错误?

        MotorImage.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {

            Intent i = new Intent(
                    Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

            startActivityForResult(i, RESULT_LOAD_IMAGE);
        }
    });
}


 @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
    Uri selectedImage = data.getData();
    String[] filePathColumn = { MediaStore.Images.Media.DATA };

    Cursor cursor = getContentResolver().query(selectedImage,
            filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    String picturePath = cursor.getString(columnIndex);
    cursor.close();


 //   
   ImageView imageView = (ImageView) findViewById(R.id.imageView1);
    imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath));



    String imageString = null;

    try {
        Bitmap bm = BitmapFactory.decodeFile(picturePath);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object  
        bm.recycle();
        byte[] b = baos.toByteArray();
        imageString = Base64.encodeToString(b, Base64.DEFAULT);
    } catch (Exception e) {
        e.printStackTrace();
    }




    Toast.makeText(getApplicationContext(), imageString, Toast.LENGTH_SHORT).show();

【问题讨论】:

  • 不要写入ByteArrayOutputStream,不要写入文件、网络套接字……你不能将任意大的数据写入内存。也不要编码为String,因为那也会写入内存。也有输出流。
  • 我想将它保存为字符串因为我将它存储在 sql server 数据库中,我应该使用什么?
  • 您不需要String,您也可以将其流式传输到您的服务器。如何取决于您的服务器和许多其他因素。
  • base64-ing 图像真的不是一个好主意,应该避免。
  • 对文件使用 Base64OutputStream。

标签: java android filestream


【解决方案1】:

我怀疑您需要缩放和重新采样您的图像以适应设备上的限制,尝试这样的操作

// decodes image and scales it to reduce memory consumption
private Bitmap decodeImage(String picturePath) {
    try {
        File file = new File(picturePath);
        // Get image size
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(file), null, opts);

        // The new size we want to scale to
        final int MIN_SIZE = 70;

        // Find the correct scale value.
        int scale = 1;
        while (((opts.outWidth / scale) >> 1) >= MIN_SIZE
                && ((opts.outHeight / scale) >> 1) >= MIN_SIZE) {
            scale <<= 1;
        }

        BitmapFactory.Options opts2 = new BitmapFactory.Options();
        opts2.inSampleSize = scale;
        return BitmapFactory.decodeStream(new FileInputStream(file), null, opts2);
    } catch (FileNotFoundException e) {
    }
    return null;
}

【讨论】:

  • 你可以用图像路径字符串而不是文件来编辑它
  • @user3245658 抱歉。我错过了。这是opts。已编辑。
  • @user3245658 我知道。但首先您必须对其进行解码和缩放,然后对其进行编码! :)
  • 所以我应该按照你的方法在这里使用我的原始帖子?
  • @user3245658 缩放图像后,您的原始方法应该可以工作;我建议您尝试使用流式解决方案(而不是内存中的解决方案)进行保存;但这应该会减少输出的大小以使其正常工作。
【解决方案2】:

尝试在 AndroidManifest 的应用标签内使用android:largeHeap="true",这样你的应用就会有更多的可用内存并且不会抛出 oom 异常。

【讨论】:

  • 你的安卓版本是多少?
【解决方案3】:

如果您阅读了android的官方文档,您就会知道这是android的常见问题,推荐的解决方案是根据您的需要调整图像大小。你也可以参考 developer.android

【讨论】:

    猜你喜欢
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多