装载大型图像,而不OutOfMemoryError异常 [英] Loading large images without 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屋!