装载大型图像,而不OutOfMemoryError异常 [英] Loading large images without OutOfMemoryError

查看:139
本文介绍了装载大型图像,而不OutOfMemoryError异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我要画到画布上5000倍4000像素的图像。

I have a 5000 x 4000 px image which I want to draw onto a canvas.

首先,我试图从资源加载它。 我把它放在 / RES /绘制

First I tried to load it from resources. I put it in /res/drawable.

我用下面的方法:

InputStream input = getResources().openRawResource(R.drawable.huge_image);
Drawable d = Drawable.createFromStream(input, "image");
d.setBounds(...);
d.draw(canvas);

这工作就像一个魅力。

It worked like a charm.

在这种情况下,的InputStream AssetManager.AssetInputStream

所以,现在我想从SD卡装入。

So now I want to load it from the sdcard.

下面就是我试图做的:

File f = new File(path);
Uri uri = Uri.fromFile(f);
InputStream input = mContext.getContentResolver().openInputStream(uri);
Drawable d = Drawable.createFromStream(input, "image");

在这种情况下,的InputStream 的FileInputStream ,我得到了一个的OutOfMemoryError 创建时,绘制对象

In this case the InputStream is a FileInputStream and I got an OutOfMemoryError when creating the Drawable.

所以,我想知道:

有没有办法来加载图像没有得到这个错误?或者是有没有办法转换的FileInputStream AssetInputStream

Is there a way to load the image without getting that error? Or is there a way to convert a FileInputStream to an AssetInputStream ?

请注意:

我不希望调整图片的大小,因为我实现缩放/平移功能。 请不要告诉我读装载大型高效位图的。

I don't want to resize the image because I'm implementing zoom/pan functionality. Please don't tell me to read Loading Large Bitmaps Efficiently.

您可以检查出完整的类<一href="https://github.com/BenitoBertoli/ZoomImageView/blob/master/src/com/benitobertoli/largeimagezoom/ZoomImageView.java">here.在使用 setImageUri()

You can check out the full class here. The error occurs when using setImageUri().

这是我的错误日志:

08-13 11:57:54.180: E/AndroidRuntime(23763): FATAL EXCEPTION: main
08-13 11:57:54.180: E/AndroidRuntime(23763): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:468)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:332)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at com.benitobertoli.largeimagezoom.ZoomImageView.setDrawablefromUri(ZoomImageView.java:187)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at com.benitobertoli.largeimagezoom.ZoomImageView.setImageUri(ZoomImageView.java:588)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at com.benitobertoli.largeimagezoom.TestActivity.onKeyDown(TestActivity.java:30)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.view.KeyEvent.dispatch(KeyEvent.java:1257)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.app.Activity.dispatchKeyEvent(Activity.java:2075)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1673)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2493)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2463)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.view.ViewRoot.handleMessage(ViewRoot.java:1752)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.os.Handler.dispatchMessage(Handler.java:99)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.os.Looper.loop(Looper.java:144)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at android.app.ActivityThread.main(ActivityThread.java:4937)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at java.lang.reflect.Method.invokeNative(Native Method)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at java.lang.reflect.Method.invoke(Method.java:521)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
08-13 11:57:54.180: E/AndroidRuntime(23763):    at dalvik.system.NativeStart.main(Native Method)

编辑:

我在测试上的HTC Desire A8181我的code。 被告知,首code段不工作的一些其他的设备后,我测试上三星Galaxy S2和模拟器。

I was testing my code on an HTC Desire A8181. After being told that the first code snippet wasn't working on some other devices, I tested on a Samsung Galaxy S2 and on the Emulator.

结果: 从资源装载时,模拟器给了一个的OutOfMemoryError ,银河S2并没有抛出异常,但返回的绘制对象为空。

Results: When loading from resources, the emulator gave an OutOfMemoryError, the Galaxy S2 didn't throw an exception but the returned Drawable was null.

所以我想暂时唯一的解决办法是下采样图像。

So I guess for the time being the only solution is to downsample the image.

推荐答案

看看:

<一个href="http://developer.android.com/reference/android/graphics/BitmapFactory.html">http://developer.android.com/reference/android/graphics/BitmapFactory.html

decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options opts)

decodeFile (String pathName, BitmapFactory.Options opts)

这种方式,您可以加载你的整个的位图,并显示在屏幕上。

this way you can load your whole bitmap and show it on screen.

您需要设置正确的选项。

You need to set the correct options.

<一个href="http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html">http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html

inSampleSize

我试了一下你的code:

I tried it with your code:

 BitmapFactory.Options options = new BitmapFactory.Options();

 options.inSampleSize = 4;

 Bitmap myBitmap = BitmapFactory.decodeFile(mUri.getPath(),options);
 Drawable d = new BitmapDrawable(Resources.getSystem(),myBitmap);
 updateDrawable(d);

我的作品。

这篇关于装载大型图像,而不OutOfMemoryError异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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