62 votes

Le décodage des images dans Android avec la bonne taille

Je décoder les images bitmap à partir de la carte SD en utilisant BitmapFactory.decodeFile. Parfois, les images sont plus grandes que ce que les besoins de l'application ou le segment de mémoire le permet, donc j'utilise BitmapFactory.Options.inSampleSize à la demande d'un sous-échantillonné (la plus petite), bitmap.

Le problème est que la plate-forme ne fait pas appliquer la valeur exacte de inSampleSize, et il m'arrive de finir avec une image soit trop petite, ou encore trop grande pour la mémoire disponible.

À partir de http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize:

Remarque: le décodeur va essayer de remplir cette demande, mais l'image résultante peut avoir des dimensions différentes que précisément ce qui a été demandé. Aussi, les puissances de 2 sont souvent plus rapide/plus facile pour le décodeur l'honneur.

Comment décoder les images bitmap à partir de la carte SD pour obtenir une image de la taille exacte, j'ai besoin de tout en consommant le moins de mémoire possible de le décoder?

Edit:

Code source de courant:

BitmapFactory.Options bounds = new BitmapFactory.Options();
this.bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, bounds);
if (bounds.outWidth == -1) { // TODO: Error }
int width = bounds.outWidth;
int height = bounds.outHeight;
boolean withinBounds = width <= maxWidth && height <= maxHeight;
if (!withinBounds) {
    int newWidth = calculateNewWidth(int width, int height);
    float sampleSizeF = (float) width / (float) newWidth;
    int sampleSize = Math.round(sampleSizeF);
    BitmapFactory.Options resample = new BitmapFactory.Options();
    resample.inSampleSize = sampleSize;
    bitmap = BitmapFactory.decodeFile(filePath, resample);
}

47voto

sirdodger Points 386

Vous êtes sur la bonne voie, mais vous essayez de faire deux choses à la fois: lire le fichier et de le dimensionner à la taille appropriée.

La première étape est de lire le fichier d'une image Bitmap légèrement plus grand que vous avez besoin, à l'aide de BitmapFactory.Des Options.inSampleSize pour vous assurer de ne pas consommer trop de mémoire de la lecture d'une grande image quand tout ce que vous voulez, c'est une miniature ou de l'écran résolution de l'image.

La deuxième étape est d'appeler Bitmap.createScaledBitmap() pour créer une nouvelle image à la résolution exacte dont vous avez besoin.

Assurez-vous de nettoyer après le bitmap temporaire pour récupérer sa mémoire. (Laisser la variable hors de portée et de laisser le GC face, ou d'appel .recycler() sur celui-ci si vous êtes le chargement des images plein et sont en cours d'exécution serrés sur la mémoire.)

17voto

TheCodeArtist Points 6837

Vous pouvez utiliser inJustDecodeBounds. Mis à TRUE et de charger le fichier tel qu'il est.

L'image ne sera pas chargé en mémoire. Mais le outheight et outwidth propriétés de BitmapFactory.Options contiendra la taille réelle params de l'image spécifiée. De calculer combien tu veux sous-échantillon. c'est à dire 1/2 ou 1/4 ou 1/8 etc. et attribuer 2/4/8 etc. en conséquence de la inSampleSize.

Maintenant fixé inJustDecodeBounds de FALSE et appelez - BitmapFactory.decodeFile() à la charge de l'image de la taille exacte calculée ci-dessus.

7voto

Ravi Bhojani Points 421

Vous devez d'abord l'échantillon de l'image à la plus proche valeur d'échantillonnage de sorte que bitmap devenir efficace en terme de mémoire, que vous avez parfaitement décrit. Une fois que c'est fait, vous pouvez mettre à l'échelle pour correspondre à votre écran.

// This function taking care of sampling
backImage =decodeSampledBitmapFromResource(getResources(),R.drawable.back, width, height);

// This will scale it to your screen width and height. you need to pass screen width and height.
backImage = Bitmap.createScaledBitmap(backImage, width, height, false); 

1voto

the100rabh Points 2978

Depuis l'API indique déjà que la taille de l'échantillon peut ou ne peut pas être honorée. Donc je suppose que ur de la chance tout en utilisant BitmapFactory .

Mais le moyen d'en sortir serait d'utiliser votre propre image bitmap lecteur. Mais je suggère que vous vous en tenez à BitmapFactory que sa assez bien testé et standardisée.

J'essayerai de ne pas trop se soucier peu de mémoire supplémentaire de la consommation, mais essayer de trouver pourquoi sa ne pas honorer les valeurs. Malheureusement je n'ai pas idée à ce propos :(

0voto

Fedor Points 29890

Depuis que j'utilise inSampleSize je n'ai jamais face à des problèmes de mémoire insuffisante. Donc inSampleSize fonctionne assez stable pour moi. Je vous recommande de vérifier la question. La taille peut être pas exactement la même comme vous l'avez demandé. Mais il devrait être réduit de toute façon et il ne devrait pas être plus de "Out of memory". Je vous recommande également de publier votre extrait de code ici, peut-être il ya quelque chose de mal avec elle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X