10 votes

Comment connaître la taille d'un Bitmap à partir de l'InputStream avant de créer le Bitmap ?

Je dois mettre à l'échelle une image avant de la créer et je ne veux le faire que si elle dépasse 1024KB (par exemple).

En faisant ce qui suit, je peux mettre l'image à l'échelle, mais je n'ai besoin de mettre à l'échelle que celles qui sont plus grandes que la taille donnée.

Bitmap bmImg = null;
InputStream is = url.openStream();
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 10;
bmImg = BitmapFactory.decodeStream(is,null,opts);

Comment puis-je obtenir la taille du bitmap (je souhaite connaître le nombre d'octets, pas la taille après décompression) ?

Edit :

J'essaie ça :

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
Bitmap bmImg=BitmapFactory.decodeStream(is,null,opts);
Log.e("optwidth",opts.outWidth+"");
Bitmap bmImg1 = BitmapFactory.decodeStream(is);

La première fois que j'utilise l'InputStream (is) pour le décoder avec la fonction "inJustDecodeBounds", cela fonctionne bien et je peux obtenir les dimensions du bitmap. Le problème est que la deuxième fois que je l'utilise pour décoder l'image, aucune image ne s'affiche.

Qu'est-ce que je fais de mal ?

0voto

NBJack Points 118

La plupart des flux sont consommés lorsque vous les lisez. Dans votre deuxième bloc de code, vous consommez le flux une première fois sous forme de bitmap. Lorsque vous invoquez decodeString une seconde fois, le flux est "vide" (ne serait-ce que dans le sens où toutes les données ont déjà été lues).

La meilleure réponse sera probablement celle de monkjack, mais peut-être avec un peu de code supplémentaire pour s'assurer que vous ne lisez pas un fichier gargantuesque en mémoire. Je recommande de vérifier la taille du fichier lorsque vous le lisez dans un tampon (par exemple, arrêtez-vous à 10 Mo) ; je ne suis pas sûr de la façon dont Android gérera une exception de mémoire insuffisante.

0voto

Ken Points 953

Si vous réduisez l'échelle pour éviter OutOfMemoryException comme moi, cette solution peut mieux fonctionner pour vous (en s'appuyant sur les réponses fournies ici) :

// <initialize stream>

// figure out number of bytes in stream
byte[] bytes = new byte[1024];
int i;
int byteCount = 0;
while ((i = stream.read(bytes)) != -1) {
    byteCount += i;
}

// <reset stream>

Bitmap bmImg;

// downsample if necessary
if (byteCount > MAX_SIZE) {
    // scale down photo if too large
    BitmapFactory.Options options = new BitmapFactory.Options();
    // scale to nearest power of 2 - faster
    options.inSampleSize = (int)Math.pow(2, (int)(Math.log10(Math.sqrt((double)byteCount / MAX_SIZE)) / Math.log10(2) + 1)); // 2 ^ (log2(lengthRatio)+1)
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
    bmImg = BitmapFactory.decodeStream(stream, null, options);
}
else {
    bmImg = BitmapFactory.decodeStream(stream);
}

J'ai évité l'utilisation de mark(int) y reset() car dans mon cas, il n'y a pas de limite supérieure à la taille du flux. La façon de réinitialiser le flux peut donc dépendre de votre implémentation. Mon flux a été spécifié par un Uri alors j'ai juste utilisé :

stream.close();
stream = this.getContentResolver().openInputStream(uri); // where this is an Activity

pour réinitialiser le flux.

0voto

sotrh Points 71

Vérifiez logcat, si vous avez une erreur qui dit "Bitmap too large to be uploaded into a texture" alors vous devez faire ce qui suit. Ma réponse est similaire à celle de @Sergio A. mais vous pouvez utiliser directement BitmapFactory.decodeStream au lieu de decodeByteArray.

final BitmapFactory.options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

// Pass in a Rect if you want to know the padding.
BitmapFactory.decodeStream(inputStream,null,options);

Cela permet d'obtenir uniquement la taille de l'image (et non l'image entière). Vous pouvez isoler la largeur et la hauteur en utilisant le code suivant.

final int height = options.outHeight;
final int width = options.outWidth;

Vous pouvez utiliser ces valeurs (ainsi que la largeur et la hauteur souhaitées - très probablement basées sur l'imageView ou l'écran) pour calculer options.inSampleSize . Je ne vais pas vous expliquer comment faire, mais Google a fourni un tutoriel. aquí .

J'espère que cela vous aidera :)

-2voto

user432209 Points 7460

Vous ne pouvez pas obtenir la taille d'un bitmap, il n'y a tout simplement pas de moyen intégré. Vous pouvez cependant obtenir la taille du contenu (un fichier), ce que vous devrez probablement faire. Quelque chose comme ceci devrait fonctionner.

int file_size = url.getContentLength();

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