Ich habe Probleme mit BitmapFactory.decodeStream(inputStream)
. Wenn Sie es ohne Optionen verwenden, wird ein Bild zurückgegeben. Aber wenn ich es mit Optionen wie in .decodeStream(inputStream, null, options)
verwende, gibt es niemals Bitmaps zurück.
Ich versuche, eine Bitmap herunterzusampeln, bevor ich sie tatsächlich lade, um Speicherplatz zu sparen. Ich habe einige gute Anleitungen gelesen, aber keine mit .decodeStream
.
WERKE NUR FEIN
URL url = new URL(sUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is, null, options);
FUNKTIONIERT NICHT
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);
Das Problem bestand darin, dass Sie, nachdem Sie einen InputStream von einer HttpUrlConnection verwendet haben, um Bildmetadaten abzurufen, nicht mehr zurückspulen und denselben InputStream erneut verwenden können.
Daher müssen Sie einen neuen InputStream für das eigentliche Sampling des Bildes erstellen.
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();
Versuchen Sie, InputStream mit BufferedInputStream zu verbinden.
InputStream is = new BufferedInputStream(conn.getInputStream());
is.mark(is.available());
// Do the bound decoding
// inJustDecodeBounds =true
is.reset();
// Do the actual decoding
Ich denke, das Problem liegt in der "Calculate-Scale-Factor" -Logik, da der Rest des Codes für mich korrekt aussieht (vorausgesetzt natürlich, dass der Eingabestrom nicht null ist).
Es ist besser, wenn Sie die gesamte Größenberechnungslogik aus dieser Routine in eine Methode zerlegen können (nennen Sie sie calculatorScaleFactor () oder was auch immer) und diese Methode zuerst unabhängig testen.
So etwas wie:
// 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);
und testen Sie getScaleFactor (...) unabhängig.
Es ist auch hilfreich, den gesamten Code mit dem try..catch {} -Block zu umgeben, falls dies noch nicht geschehen ist.
Sie können den InputStream in ein Byte-Array konvertieren und decodeByteArray () verwenden. Beispielsweise,
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;
}