93 votes

BitmapFactory.decodeStream renvoyant la valeur null lorsque les options sont définies

Je vais avoir des problèmes avec BitmapFactory.decodeStream(inputStream). Lors de l'utilisation sans options, il sera de retour d'une image. Mais quand je l'utilise avec des options comme en .decodeStream(inputStream, null, options) il ne revient jamais d'images.

Ce que j'essaie de faire est de sous-échantillonner une image Bitmap avant que je le charge pour économiser de la mémoire. J'ai lu quelques guides de bonnes, mais aucun à l'aide de .decodeStream.

FONCTIONNE TRÈS BIEN

URL url = new URL(sUrl);
HttpURLConnection connection  = (HttpURLConnection) url.openConnection();

InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is, null, options);

NE FONCTIONNE PAS

InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is, null, options);

InputStream is = connection.getInputStream();

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

BitmapFactory.decodeStream(is, null, options);

Boolean scaleByHeight = Math.abs(options.outHeight - TARGET_HEIGHT) >= Math.abs(options.outWidth - TARGET_WIDTH);

if (options.outHeight * options.outWidth * 2 >= 200*100*2){
    // Load, scaling to smallest power of 2 that'll get it <= desired dimensions
    double sampleSize = scaleByHeight
    ? options.outHeight / TARGET_HEIGHT
    : options.outWidth / TARGET_WIDTH;
    options.inSampleSize =
        (int)Math.pow(2d, Math.floor(
        Math.log(sampleSize)/Math.log(2d)));
}

// Do the actual decoding
options.inJustDecodeBounds = false;
Bitmap img = BitmapFactory.decodeStream(is, null, options);

115voto

Robert Foss Points 951

Le problème était qu'une fois que vous avez utilisé un InputStream à partir d'un HttpUrlConnection pour extraire des métadonnées d'image, vous ne pouvez pas revenir en arrière et utiliser à nouveau le même InputStream.

Par conséquent, vous devez créer un nouveau InputStream pour l'échantillonnage réel de l'image.

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

  BitmapFactory.decodeStream(is, null, options);

  Boolean scaleByHeight = Math.abs(options.outHeight - TARGET_HEIGHT) >= Math.abs(options.outWidth - TARGET_WIDTH);

  if(options.outHeight * options.outWidth * 2 >= 200*200*2){
         // Load, scaling to smallest power of 2 that'll get it <= desired dimensions
        double sampleSize = scaleByHeight
              ? options.outHeight / TARGET_HEIGHT
              : options.outWidth / TARGET_WIDTH;
        options.inSampleSize = 
              (int)Math.pow(2d, Math.floor(
              Math.log(sampleSize)/Math.log(2d)));
     }

        // Do the actual decoding
        options.inJustDecodeBounds = false;

        is.close();
        is = getHTTPConnectionInputStream(sUrl);
        Bitmap img = BitmapFactory.decodeStream(is, null, options);
        is.close();
 

30voto

Jett Hsieh Points 2227

Essayez d'encapsuler InputStream avec BufferedInputStream.

 InputStream is = new BufferedInputStream(conn.getInputStream());
is.mark(is.available());
// Do the bound decoding
// inJustDecodeBounds =true
is.reset();  
// Do the actual decoding
 

3voto

Samuh Points 16564

Je pense que le problème est avec le "calculer à l'échelle du facteur" logique car reste du code est correct pour moi (en supposant bien sûr que inputstream is not null).

Il serait mieux si vous pouvez le facteur de tous le calcul de la taille de la logique de cette routine dans une méthode(que l'on appellera calculateScaleFactor() ou quoi que ce soit) et de tester cette méthode de façon indépendante de la première.

Quelque chose comme:

// Get the stream 
InputStream is = mUrl.openStream();

// get the Image bounds
BitmapFactory.Options options=new BitmapFactory.Options(); 
options.inJustDecodeBounds = true;

bitmap = BitmapFactory.decodeStream(is,null,options);

//get actual width x height of the image and calculate the scale factor
options.inSampleSize = getScaleFactor(options.outWidth,options.outHeight,
                view.getWidth(),view.getHeight());

options.inJustDecodeBounds = false;
bitmap=BitmapFactory.decodeStream(mUrl.openStream(),null,options);

et test getScaleFactor(...) de manière indépendante.

Il aidera aussi à entourer le code entier avec try..catch{} bloc, si ce n'est déjà fait.

-1voto

Shashank Tomar Points 512

La lecture du flux se fait par lots, une fois que votre pointeur est terminé. Vous devez le réinitialiser avant de l'utiliser à nouveau. Donc, procédez comme suit avant de l'utiliser à nouveau (c'est-à-dire avant la dernière ligne de l'exemple de code que vous avez donné ci-dessus)

 is.reset();
 

Cela a résolu le problème pour moi.

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