Le chargement des images de grande taille sans OutOfMemoryError

J'ai un 5000 x 4000 px image que je veux dessiner sur une toile.

J'ai d'abord essayé de le charger à partir de ressources.
Je l'ai mis dans /res/drawable.

J'ai utilisé la méthode suivante:

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

Il a travaillé comme un charme.

Dans ce cas, le InputStream est un AssetManager.AssetInputStream.

Alors maintenant je veux le charger à partir de la carte sd.

Voici ce que j'ai essayé de faire:

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

Dans ce cas, le InputStream est un FileInputStream et j'ai eu un OutOfMemoryError lors de la création de la Drawable.

Alors je me demandais:

Est-il un moyen de charger l'image sans avoir d'erreur? Ou est-il un moyen de convertir un FileInputStream à un AssetInputStream ?

Remarque:

Je ne veux pas redimensionner l'image, parce que je suis la mise en œuvre de zoom/pan fonctionnalité.
S'il vous plaît ne me dites pas de lire Le Chargement D'Un Grand Bitmaps Efficacement.

Vous pouvez vérifier l'intégralité de la classe ici. L'erreur se produit lors de l'utilisation de setImageUri().

Voici mon Log d'Erreur:

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:

J'ai été le tester mon code sur un HTC Desire A8181.
Après avoir appris que le premier extrait de code ne fonctionnait pas sur certains autres appareils, j'ai testé sur un Samsung Galaxy S2 et sur l'Émulateur.

Résultats:
Lors du chargement de ressources, l'émulateur a donné un OutOfMemoryError, le Galaxy S2 n'a pas de jeter une exception, mais le retour Drawable était nulle.

Donc je suppose que pour le moment la seule solution est de sous-échantillonner l'image.

J'ai essayé de l'exécution de votre code sur m émulateur et j'obtiens l'erreur OutOfMemory même sur les "renouvelables" méthode 🙂 Ce dispositif et/ou les paramètres de l'émulateur que vous utilisez et qui était capable de l'exécuter sans erreur?

OriginalL'auteur Benito Bertoli | 2012-08-13