BitmapFactory.decodeStream возвращает значение null при настройке параметров

У меня проблемы с BitmapFactory.decodeStream(inputStream) . Если вы используете его без параметров, он вернет изображение. Но когда я использую его с параметрами, как в .decodeStream(inputStream, null, options) он никогда не возвращает битмапы.

То, что я пытаюсь сделать, – это уменьшить размер растрового изображения, прежде чем я загружу его для сохранения памяти. Я прочитал несколько полезных руководств, но никто не использовал .decodeStream .

РАБОТЫ ПРОСТО

 URL url = new URL(sUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); InputStream is = connection.getInputStream(); Bitmap img = BitmapFactory.decodeStream(is, null, options); 

НЕ РАБОТАЕТ

 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); 

Проблема заключалась в том, что после того, как вы использовали InputStream из HttpUrlConnection для извлечения метаданных изображения, вы не можете перемотать назад и снова использовать тот же InputStream.

Поэтому вам необходимо создать новый InputStream для фактической выборки изображения.

  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(); 

Попробуйте обернуть InputStream с помощью BufferedInputStream.

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

Я думаю, что проблема связана с логикой «калькулятор-масштаб», потому что остальная часть кода выглядит правильно для меня (предполагая, конечно, что входной поток не является нулевым).

Было бы лучше, если бы вы могли отчислить всю логику вычисления размера из этой подпрограммы в метод (назовите его calculateScaleFactor () или что-то еще) и сначала сначала проверите этот метод.

Что-то вроде:

 // 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); 

И test getScaleFactor (…) самостоятельно.

Это также поможет объединить весь код с помощью try..catch {} block, если это уже не сделано.

Вы можете преобразовать InputStream в массив байтов и использовать decodeByteArray (). Например,

 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; }