加载没有OutOfMemoryError的大图像

Ben*_*oli 16 java android android-image android-canvas

我有一个5000 x 4000 px图像,我想画在画布上.

首先,我尝试从资源加载它.我把它放进去了/res/drawable.

我使用以下方法:

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

它就像一个魅力.

在这种情况下,InputStream是一个AssetManager.AssetInputStream.

所以现在我想从SD卡加载它.

这是我试图做的事情:

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

在这种情况下InputStream是a FileInputStream,我OutOfMemoryError在创建时得到了Drawable.

所以我想知道:

有没有办法加载图像而不会出现错误?或者有没有办法将a转换FileInputStreamAssetInputStream

注意:

我不想调整图像大小,因为我正在实现缩放/平移功能.请不要告诉我阅读有效加载大位图.

你可以在这里查看全班.使用时发生错误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)
Run Code Online (Sandbox Code Playgroud)

编辑:

我在HTC Desire A8181上测试我的代码.在被告知第一个代码片段不能用于其他设备之后,我在三星Galaxy S2和仿真器上进行了测试.

结果:从资源加载时,模拟器给出了一个OutOfMemoryError,Galaxy S2没有抛出异常,但返回的Drawable是null.

所以我想暂时唯一的解决方案是对图像进行下采样.

n3u*_*ino 13

看一眼:

http://developer.android.com/reference/android/graphics/BitmapFactory.html

decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options opts)
Run Code Online (Sandbox Code Playgroud)

要么

decodeFile (String pathName, BitmapFactory.Options opts)
Run Code Online (Sandbox Code Playgroud)

这样您就可以加载整个位图并在屏幕上显示.

您需要设置正确的选项.

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html

inSampleSize
Run Code Online (Sandbox Code Playgroud)

我用你的代码试了一下:

 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);
Run Code Online (Sandbox Code Playgroud)

适合我.

  • 你需要**来缩放和平铺你不能在内存中保存位图5000x4000px.要缩放和平移你需要弄清楚原始图像的哪个部分是可见的,并加载相应的瓷砖缩放到屏幕的密度 (2认同)