Ich habe ein 5000 x 4000 px Bild, das ich auf eine Leinwand zeichnen möchte.Loading große Bilder ohne OutOfMemoryError
Zuerst habe ich versucht, es von Ressourcen zu laden. Ich lege es in /res/drawable
.
habe ich die folgende Methode:
InputStream input = getResources().openRawResource(R.drawable.huge_image);
Drawable d = Drawable.createFromStream(input, "image");
d.setBounds(...);
d.draw(canvas);
Es arbeitete wie ein Charme. In diesem Fall ist ein AssetManager.AssetInputStream
.
So jetzt möchte ich es von der SD-Karte laden.
Hier ist, was ich versucht zu tun:
File f = new File(path);
Uri uri = Uri.fromFile(f);
InputStream input = mContext.getContentResolver().openInputStream(uri);
Drawable d = Drawable.createFromStream(input, "image");
In diesem Fall wird die InputStream
ein FileInputStream
ist, und ich habe eine OutOfMemoryError
wenn die Drawable
zu schaffen.
Also ich frage mich:
Gibt es eine Möglichkeit, das Bild zu laden, ohne dass Fehler zu bekommen? Oder gibt es eine Möglichkeit, eine FileInputStream
in eine AssetInputStream
umzuwandeln?
Hinweis:
Ich möchte nicht das Bild, um die Größe, weil ich Zoom/Pan-Funktionalität bin zu implementieren. Bitte sagen Sie mir nicht zu lesen Loading Large Bitmaps Efficiently.
Sie können die gesamte Klasse here überprüfen. Der Fehler tritt auf, wenn setImageUri()
verwendet wird.
Hier ist mein Fehlerprotokoll:
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)
EDIT:
Ich teste meinen Code auf einem HTC Desire A8181. Nachdem mir gesagt wurde, dass das erste Code-Snippet auf einigen anderen Geräten nicht funktionierte, habe ich auf einem Samsung Galaxy S2 und auf dem Emulator getestet.
Ergebnisse: Wenn von Ressourcen Laden, gab den Emulator ein OutOfMemoryError
, nicht das Galaxy S2 eine Ausnahme aus, aber die zurück Drawable
war null.
Also ich denke, vorläufig ist die einzige Lösung, das Bild zu verkleinern.
Ich habe versucht, Ihren Code auf m Emulator laufen und bekomme den OutOfMemory Fehler sogar auf der "From Res" -Methode :) Welche Geräte und/oder Emulator-Einstellungen, die Sie verwenden, konnte es ohne Fehler ausführen? – Joe