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 ?

5voto

Scott Roberts Points 191

Je suis un noob donc je ne peux pas commenter directement la réponse de monkjack. La raison pour laquelle sa réponse est si lente est qu'elle copie un octet à la fois. L'utilisation d'un tampon, même de 1K, améliorera considérablement les performances.

InputStream in = getContentResolver().openInputStream(docUri);

ByteArrayOutputStream bos = new ByteArrayOutputStream();
int i;
byte[] buffer = new byte[1024];
while ((i = in.read(buffer)) != -1) {
    bos.write(buffer);
}
byte[] docbuffer = bos.toByteArray();

3voto

Sergio A. Points 21

Si vous essayez d'empêcher le OutOfMemory ou autre chose...

vous pouvez créer un tampon avec vos données d'image,

BitmapFactory.Options buffer = new BitmapFactory.Options();
buffer.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(photo, 0, photo.length, buffer);

Ensuite, vous pouvez obtenir la taille en utilisant buffer.outHeight, buffer.outWidth

Si vous voulez mettre à l'échelle, il vous suffit d'utiliser buffer.isSampleSize mais j'ai remarqué que vous y fixez une valeur de "10"... ce qui me semble erroné... sampleSize devrait obtenir une valeur de 2^ ... comme 2,4,8,16 etc....

Enfin, après avoir défini le paramètre sampleSize, vous pouvez créer le bitmap comme toujours.

Bitmap bmp = BitmapFactory.decodeByteArray(photo, 0, photo.length, buffer);

J'espère vous aider !

PS : SQS MON ANGLAIS =( !!!)

2voto

Si vous connaissez le format du fichier, vous pourrez peut-être lire l'en-tête du fichier. Habituellement, l'en-tête contient la taille et le format de l'image. Et heureusement pour vous, il s'agit toujours des premiers octets du fichier.

Cela pourrait ne pas être possible pour certains types.

PNG , JPEG , BMP , TGA

Il suffit de lire l'en-tête et certains fichiers dont vous devez d'abord deviner la largeur. Par exemple, le PNG ne semble pas inclure la largeur et la hauteur, mais vous devriez être en mesure de lire la largeur et de deviner la hauteur avec la taille des pixels et le ratio.

Edit : My bad Je pensais que vous vouliez mettre à l'échelle en utilisant la dimension... Oui ContentLenght devrait aider mais parfois il retournera 0 si le serveur n'a pas défini la bonne dimension dans l'en-tête http. Dans ce cas, vous devez connaître la taille retournée. Mais de toute façon, vous pouvez sauvegarder un tableau d'octets et une fois que tout est chargé, vérifiez la longueur du tableau. Si elle est supérieure à 1024kb, redimensionnez l'image. Et enregistrez-la ou faites-en ce que vous voulez.

2voto

Adam Bryzak Points 1602

Vous pouvez envelopper is avec un new BufferedInputStream(is); et utiliser le mark(int readlimit) y reset() pour relire le flux. Vous devrez décider ce qu'il faut mettre readlimit pour lui permettre de lire l'intégralité de l'en-tête, les liens fournis par Loïc devraient vous aider ici.

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

J'ai laissé de côté la gestion appropriée des erreurs pour la fonction reset() il lancera un IOException si vous avez lu plus de readlimit octets du flux.

0voto

monkjack Points 4727

Vous ne pouvez pas obtenir la taille d'un flux par sa définition même. Si vous le souhaitez, vous pouvez charger le flux dans un tableau d'octets et obtenir le nombre d'octets à partir de celui-ci. Vous pouvez également utiliser le BitmapFactory pour décoder directement un tableau d'octets, ce qui fonctionnerait très bien.

InputStream in = ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int i;
while ((i = in.read()) != -1) {
    bos.write(i);
}
byte[] byteArray = bos.toByteArray();
if (byteArray.length > SOME_VALUE) { 
    // do things here
}
BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);

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