Mam problemy z BitmapFactory.decodeStream(inputStream)
. Używając go bez opcji, zwróci obraz. Ale kiedy używam go z opcjami, ponieważ .decodeStream(inputStream, null, options)
nigdy nie zwraca bitmap.
To, co próbuję zrobić, to zmniejszyć próbkowanie mapy bitowej, zanim faktycznie ją załaduję, aby zaoszczędzić pamięć. Przeczytałem kilka dobrych przewodników, ale żaden nie używa .decodeStream
.
DZIAŁA WYJĄTKOWO DOBRZE
URL url = new URL(sUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is, null, options);
NIE DZIAŁA
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);
Odpowiedzi:
Problem polegał na tym, że po użyciu InputStream z HttpUrlConnection do pobrania metadanych obrazu nie można przewinąć i ponownie użyć tego samego InputStream.
Dlatego musisz utworzyć nowy InputStream dla faktycznego próbkowania obrazu.
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();
źródło
Spróbuj opakować InputStream za pomocą BufferedInputStream.
InputStream is = new BufferedInputStream(conn.getInputStream()); is.mark(is.available()); // Do the bound decoding // inJustDecodeBounds =true is.reset(); // Do the actual decoding
źródło
Myślę, że problem tkwi w logice "obliczania współczynnika skali", ponieważ reszta kodu wygląda na poprawną (zakładając oczywiście, że strumień wejściowy nie jest zerowy).
Byłoby lepiej, gdybyś mógł rozliczyć całą logikę obliczania rozmiaru z tej procedury na metodę (wywołać ją calcScaleFactor () lub cokolwiek innego) i najpierw przetestować tę metodę niezależnie.
Coś jak:
// 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);
i niezależnie przetestuj getScaleFactor (...).
Pomoże również otoczyć cały kod blokiem try..catch {}, jeśli nie zostało to jeszcze zrobione.
źródło
Możesz przekonwertować InputStream na tablicę bajtów i użyć decodeByteArray (). Na przykład,
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; }
źródło