Je rencontre des problèmes avec BitmapFactory.decodeStream(inputStream)
. Lorsque vous l'utilisez sans options, il renverra une image. Mais lorsque je l'utilise avec des options comme dans .decodeStream(inputStream, null, options)
, il ne renvoie jamais de bitmaps.
Ce que j'essaie de faire, c'est de sous-échantillonner un bitmap avant de le charger pour économiser de la mémoire. J'ai lu de bons guides, mais aucun en utilisant .decodeStream
.
FONCTIONNE JUSTE FIN
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);
Le problème était qu'une fois que vous avez utilisé un InputStream à partir d'un HttpUrlConnection pour récupérer les métadonnées d'image, vous ne pouvez pas rembobiner 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();
Essayez d'envelopper 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
Je pense que le problème vient de la logique du "calcul d'échelle" car le reste du code me semble correct (en supposant bien sûr que le flux d'entrée n'est pas nul).
Il serait préférable que vous puissiez factoriser toute la logique de calcul de la taille de cette routine dans une méthode (appelez-la CalculateScaleFactor () ou autre) et testez d'abord cette méthode indépendamment.
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 testez getScaleFactor (...) indépendamment.
Cela aidera également à entourer le code entier avec le bloc try..catch {}, si ce n'est déjà fait.
Vous pouvez convertir InputStream en un tableau d'octets et utiliser decodeByteArray (). Par exemple,
public static Bitmap decodeSampledBitmapFromStream(InputStream inputStream, int reqWidth, int reqHeight) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
int n;
byte[] buffer = new byte[1024];
while ((n = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, n);
}
return decodeSampledBitmapFromByteArray(outputStream.toByteArray(), reqWidth, reqHeight);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public static Bitmap decodeSampledBitmapFromByteArray(byte[] data, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int
reqHeight) {
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (width > reqWidth || height > reqHeight) {
int halfWidth = width / 2;
int halfHeight = height / 2;
while (halfWidth / inSampleSize >= reqWidth && halfHeight / inSampleSize >= reqHeight) {
inSampleSize *= 2;
}
}
return inSampleSize;
}